]> Zhao Yanbai Git Server - minix.git/commitdiff
Initial import of libsa, libkern, bootxx, boot.
authorEvgeniy Ivanov <lolkaantimat@gmail.com>
Mon, 9 Jan 2012 14:07:58 +0000 (18:07 +0400)
committerBen Gras <ben@minix3.org>
Thu, 9 Feb 2012 17:48:13 +0000 (18:48 +0100)
322 files changed:
man/man5/Makefile
man/man5/boot.cfg.5 [new file with mode: 0644]
man/man8/boot.8
sys/arch/i386/stand/boot/Makefile [new file with mode: 0644]
sys/arch/i386/stand/boot/Makefile.boot [new file with mode: 0644]
sys/arch/i386/stand/boot/biosboot.S [new file with mode: 0644]
sys/arch/i386/stand/boot/biosboot/Makefile [new file with mode: 0644]
sys/arch/i386/stand/boot/boot2.c [new file with mode: 0644]
sys/arch/i386/stand/boot/conf.c [new file with mode: 0644]
sys/arch/i386/stand/boot/devopen.c [new file with mode: 0644]
sys/arch/i386/stand/boot/devopen.h [new file with mode: 0644]
sys/arch/i386/stand/boot/version [new file with mode: 0644]
sys/arch/i386/stand/bootxx/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/Makefile.bootxx [new file with mode: 0644]
sys/arch/i386/stand/bootxx/boot1.c [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx.S [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile [new file with mode: 0644]
sys/arch/i386/stand/bootxx/label.S [new file with mode: 0644]
sys/arch/i386/stand/bootxx/pbr.S [new file with mode: 0644]
sys/arch/i386/stand/lib/Makefile [new file with mode: 0644]
sys/arch/i386/stand/lib/Makefile.inc [new file with mode: 0644]
sys/arch/i386/stand/lib/bios_disk.S [new file with mode: 0644]
sys/arch/i386/stand/lib/bios_pci.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosdelay.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosdisk.c [new file with mode: 0644]
sys/arch/i386/stand/lib/biosdisk.h [new file with mode: 0644]
sys/arch/i386/stand/lib/biosdisk_ll.c [new file with mode: 0644]
sys/arch/i386/stand/lib/biosdisk_ll.h [new file with mode: 0644]
sys/arch/i386/stand/lib/biosgetrtc.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosgetsystime.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosmca.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosmca.h [new file with mode: 0644]
sys/arch/i386/stand/lib/biosmem.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosmemps2.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosmemx.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biospci.c [new file with mode: 0644]
sys/arch/i386/stand/lib/biosreboot.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosvbe.S [new file with mode: 0644]
sys/arch/i386/stand/lib/biosvideomode.S [new file with mode: 0644]
sys/arch/i386/stand/lib/boot_params.S [new file with mode: 0644]
sys/arch/i386/stand/lib/bootinfo.c [new file with mode: 0644]
sys/arch/i386/stand/lib/bootinfo.h [new file with mode: 0644]
sys/arch/i386/stand/lib/bootinfo_biosgeom.c [new file with mode: 0644]
sys/arch/i386/stand/lib/bootinfo_memmap.c [new file with mode: 0644]
sys/arch/i386/stand/lib/bootmenu.c [new file with mode: 0644]
sys/arch/i386/stand/lib/bootmenu.h [new file with mode: 0644]
sys/arch/i386/stand/lib/bootmod.h [new file with mode: 0644]
sys/arch/i386/stand/lib/comio.S [new file with mode: 0644]
sys/arch/i386/stand/lib/comio_direct.c [new file with mode: 0644]
sys/arch/i386/stand/lib/comio_direct.h [new file with mode: 0644]
sys/arch/i386/stand/lib/conio.S [new file with mode: 0644]
sys/arch/i386/stand/lib/cpufunc.S [new file with mode: 0644]
sys/arch/i386/stand/lib/cpufunc.h [new file with mode: 0644]
sys/arch/i386/stand/lib/crt/dos/doscommain.c [new file with mode: 0644]
sys/arch/i386/stand/lib/crt/dos/start_dos.S [new file with mode: 0644]
sys/arch/i386/stand/lib/diskbuf.c [new file with mode: 0644]
sys/arch/i386/stand/lib/diskbuf.h [new file with mode: 0644]
sys/arch/i386/stand/lib/dos_file.S [new file with mode: 0644]
sys/arch/i386/stand/lib/dosfile.c [new file with mode: 0644]
sys/arch/i386/stand/lib/dosfile.h [new file with mode: 0644]
sys/arch/i386/stand/lib/dump_eax.S [new file with mode: 0644]
sys/arch/i386/stand/lib/exec.c [new file with mode: 0644]
sys/arch/i386/stand/lib/gatea20.c [new file with mode: 0644]
sys/arch/i386/stand/lib/getextmemx.c [new file with mode: 0644]
sys/arch/i386/stand/lib/getsecs.c [new file with mode: 0644]
sys/arch/i386/stand/lib/isadma.c [new file with mode: 0644]
sys/arch/i386/stand/lib/isadmavar.h [new file with mode: 0644]
sys/arch/i386/stand/lib/isapnp.c [new file with mode: 0644]
sys/arch/i386/stand/lib/isapnpvar.h [new file with mode: 0644]
sys/arch/i386/stand/lib/libi386.h [new file with mode: 0644]
sys/arch/i386/stand/lib/menuutils.c [new file with mode: 0644]
sys/arch/i386/stand/lib/message.S [new file with mode: 0644]
sys/arch/i386/stand/lib/message32.S [new file with mode: 0644]
sys/arch/i386/stand/lib/multiboot.S [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/3c509.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/3c509.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/3c590.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/3c90xb.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/Makefile.inc [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/am7990.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/dp8390.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/dp8390.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/elink3.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/etherdrv.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/i82557.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/lance.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/ne.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/ne.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/netif_small.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/netif_small.h [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/pcnet_isapnp.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/pcnet_pci.c [new file with mode: 0644]
sys/arch/i386/stand/lib/netif/wd80x3.c [new file with mode: 0644]
sys/arch/i386/stand/lib/parseutils.c [new file with mode: 0644]
sys/arch/i386/stand/lib/pcio.c [new file with mode: 0644]
sys/arch/i386/stand/lib/pcivar.h [new file with mode: 0644]
sys/arch/i386/stand/lib/pread.c [new file with mode: 0644]
sys/arch/i386/stand/lib/printmemlist.c [new file with mode: 0644]
sys/arch/i386/stand/lib/putstr.S [new file with mode: 0644]
sys/arch/i386/stand/lib/putstr32.S [new file with mode: 0644]
sys/arch/i386/stand/lib/pvcopy.S [new file with mode: 0644]
sys/arch/i386/stand/lib/rasops.c [new file with mode: 0644]
sys/arch/i386/stand/lib/realprot.S [new file with mode: 0644]
sys/arch/i386/stand/lib/startprog.S [new file with mode: 0644]
sys/arch/i386/stand/lib/test/Makefile.satest [new file with mode: 0644]
sys/arch/i386/stand/lib/test/biosdisk_user.c [new file with mode: 0644]
sys/arch/i386/stand/lib/test/biosdisk_user.h [new file with mode: 0644]
sys/arch/i386/stand/lib/test/ether_bpf.c [new file with mode: 0644]
sys/arch/i386/stand/lib/test/pci_user.c [new file with mode: 0644]
sys/arch/i386/stand/lib/test/sanamespace.h [new file with mode: 0644]
sys/arch/i386/stand/lib/test/stand_user.c [new file with mode: 0644]
sys/arch/i386/stand/lib/vbe.c [new file with mode: 0644]
sys/arch/i386/stand/lib/vbe.h [new file with mode: 0644]
sys/lib/libkern/Makefile [new file with mode: 0644]
sys/lib/libkern/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/Makefile.libkern [new file with mode: 0644]
sys/lib/libkern/__main.c [new file with mode: 0644]
sys/lib/libkern/arc4random.c [new file with mode: 0644]
sys/lib/libkern/arch/alpha/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/alpha/divrem.m4 [new file with mode: 0644]
sys/lib/libkern/arch/alpha/htonl.S [new file with mode: 0644]
sys/lib/libkern/arch/alpha/htons.S [new file with mode: 0644]
sys/lib/libkern/arch/alpha/ntohl.S [new file with mode: 0644]
sys/lib/libkern/arch/alpha/ntohs.S [new file with mode: 0644]
sys/lib/libkern/arch/arm/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/arm/clzsi2.S [new file with mode: 0644]
sys/lib/libkern/arch/hppa/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/hppa/bcopy.S [new file with mode: 0644]
sys/lib/libkern/arch/hppa/memcpy.S [new file with mode: 0644]
sys/lib/libkern/arch/hppa/memmove.S [new file with mode: 0644]
sys/lib/libkern/arch/hppa/milli.S [new file with mode: 0644]
sys/lib/libkern/arch/hppa/prefix.h [new file with mode: 0644]
sys/lib/libkern/arch/hppa/spcopy.S [new file with mode: 0644]
sys/lib/libkern/arch/i386/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/i386/random.S [new file with mode: 0644]
sys/lib/libkern/arch/i386/scanc.S [new file with mode: 0644]
sys/lib/libkern/arch/i386/skpc.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/ia64/bswap16.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/bswap32.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/bswap64.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/byte_swap_2.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/byte_swap_4.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/byte_swap_8.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/divdi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/divsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/htonl.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/memcpy.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/moddi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/modsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/ntohl.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/udivdi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/udivsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/umoddi3.S [new file with mode: 0644]
sys/lib/libkern/arch/ia64/umodsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/m68k/DEFS.h [new file with mode: 0644]
sys/lib/libkern/arch/m68k/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/m68k/random.S [new file with mode: 0644]
sys/lib/libkern/arch/m68k/scanc.S [new file with mode: 0644]
sys/lib/libkern/arch/m68k/skpc.S [new file with mode: 0644]
sys/lib/libkern/arch/mips/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/powerpc/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/powerpc/gprsavrest.S [new file with mode: 0644]
sys/lib/libkern/arch/powerpc/memset.S [new file with mode: 0644]
sys/lib/libkern/arch/powerpc/syncicache.c [new file with mode: 0644]
sys/lib/libkern/arch/sh3/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/sh3/ashiftrt.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/ashlsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/ashrsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/byte_swap_2.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/byte_swap_4.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/byte_swap_8.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/lshrsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/movstr.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/movstrSI.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/movstrSI12_i4.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/movstr_i4.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/mulsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/sdivsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/sdivsi3_i4i.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/udivsi3.S [new file with mode: 0644]
sys/lib/libkern/arch/sh3/udivsi3_i4i.S [new file with mode: 0644]
sys/lib/libkern/arch/sparc/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/sparc/divrem.m4 [new file with mode: 0644]
sys/lib/libkern/arch/sparc/random.S [new file with mode: 0644]
sys/lib/libkern/arch/sparc64/DEFS.h [new file with mode: 0644]
sys/lib/libkern/arch/sparc64/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/sparc64/divrem.m4 [new file with mode: 0644]
sys/lib/libkern/arch/sparc64/random.S [new file with mode: 0644]
sys/lib/libkern/arch/usermode/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/vax/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/vax/blkcpy.S [new file with mode: 0644]
sys/lib/libkern/arch/vax/blkset.S [new file with mode: 0644]
sys/lib/libkern/arch/vax/random.S [new file with mode: 0644]
sys/lib/libkern/arch/x86_64/Makefile.inc [new file with mode: 0644]
sys/lib/libkern/arch/x86_64/random.S [new file with mode: 0644]
sys/lib/libkern/arch/x86_64/scanc.S [new file with mode: 0644]
sys/lib/libkern/arch/x86_64/skpc.S [new file with mode: 0644]
sys/lib/libkern/bcd.c [new file with mode: 0644]
sys/lib/libkern/crc32.c [new file with mode: 0644]
sys/lib/libkern/crc32.h [new file with mode: 0644]
sys/lib/libkern/imax.c [new file with mode: 0644]
sys/lib/libkern/imin.c [new file with mode: 0644]
sys/lib/libkern/intoa.c [new file with mode: 0644]
sys/lib/libkern/kern_assert.c [new file with mode: 0644]
sys/lib/libkern/libkern.h [new file with mode: 0644]
sys/lib/libkern/lmax.c [new file with mode: 0644]
sys/lib/libkern/lmin.c [new file with mode: 0644]
sys/lib/libkern/max.c [new file with mode: 0644]
sys/lib/libkern/mertwist.c [new file with mode: 0644]
sys/lib/libkern/milieu.h [new file with mode: 0644]
sys/lib/libkern/min.c [new file with mode: 0644]
sys/lib/libkern/pmatch.c [new file with mode: 0644]
sys/lib/libkern/rngtest.c [new file with mode: 0644]
sys/lib/libkern/scanc.c [new file with mode: 0644]
sys/lib/libkern/skpc.c [new file with mode: 0644]
sys/lib/libkern/softfloat-macros.h [new file with mode: 0644]
sys/lib/libkern/softfloat-specialize.h [new file with mode: 0644]
sys/lib/libkern/softfloat.c [new file with mode: 0644]
sys/lib/libkern/softfloat.h [new file with mode: 0644]
sys/lib/libkern/ulmax.c [new file with mode: 0644]
sys/lib/libkern/ulmin.c [new file with mode: 0644]
sys/lib/libkern/xlat_mbr_fstype.c [new file with mode: 0644]
sys/lib/libsa/Makefile [new file with mode: 0644]
sys/lib/libsa/Makefile.inc [new file with mode: 0644]
sys/lib/libsa/alloc.c [new file with mode: 0644]
sys/lib/libsa/arp.c [new file with mode: 0644]
sys/lib/libsa/bootp.c [new file with mode: 0644]
sys/lib/libsa/bootp.h [new file with mode: 0644]
sys/lib/libsa/bootparam.c [new file with mode: 0644]
sys/lib/libsa/bootparam.h [new file with mode: 0644]
sys/lib/libsa/byteorder.c [new file with mode: 0644]
sys/lib/libsa/byteorder.h [new file with mode: 0644]
sys/lib/libsa/cd9660.c [new file with mode: 0644]
sys/lib/libsa/cd9660.h [new file with mode: 0644]
sys/lib/libsa/checkpasswd.c [new file with mode: 0644]
sys/lib/libsa/close.c [new file with mode: 0644]
sys/lib/libsa/closeall.c [new file with mode: 0644]
sys/lib/libsa/cread.c [new file with mode: 0644]
sys/lib/libsa/dev.c [new file with mode: 0644]
sys/lib/libsa/dev_net.c [new file with mode: 0644]
sys/lib/libsa/dev_net.h [new file with mode: 0644]
sys/lib/libsa/disklabel.c [new file with mode: 0644]
sys/lib/libsa/dkcksum.c [new file with mode: 0644]
sys/lib/libsa/dosfs.c [new file with mode: 0644]
sys/lib/libsa/dosfs.h [new file with mode: 0644]
sys/lib/libsa/errno.c [new file with mode: 0644]
sys/lib/libsa/ether.c [new file with mode: 0644]
sys/lib/libsa/ether_sprintf.c [new file with mode: 0644]
sys/lib/libsa/exec.c [new file with mode: 0644]
sys/lib/libsa/exit.c [new file with mode: 0644]
sys/lib/libsa/ext2fs.c [new file with mode: 0644]
sys/lib/libsa/ext2fs.h [new file with mode: 0644]
sys/lib/libsa/ffsv1.c [new file with mode: 0644]
sys/lib/libsa/ffsv2.c [new file with mode: 0644]
sys/lib/libsa/files.c [new file with mode: 0644]
sys/lib/libsa/fstat.c [new file with mode: 0644]
sys/lib/libsa/getfile.c [new file with mode: 0644]
sys/lib/libsa/gets.c [new file with mode: 0644]
sys/lib/libsa/globals.c [new file with mode: 0644]
sys/lib/libsa/ioctl.c [new file with mode: 0644]
sys/lib/libsa/iodesc.h [new file with mode: 0644]
sys/lib/libsa/ip.c [new file with mode: 0644]
sys/lib/libsa/ip_cksum.c [new file with mode: 0644]
sys/lib/libsa/lfs.h [new file with mode: 0644]
sys/lib/libsa/lfsv1.c [new file with mode: 0644]
sys/lib/libsa/lfsv2.c [new file with mode: 0644]
sys/lib/libsa/loadfile.c [new file with mode: 0644]
sys/lib/libsa/loadfile.h [new file with mode: 0644]
sys/lib/libsa/loadfile_aout.c [new file with mode: 0644]
sys/lib/libsa/loadfile_ecoff.c [new file with mode: 0644]
sys/lib/libsa/loadfile_elf32.c [new file with mode: 0644]
sys/lib/libsa/loadfile_elf64.c [new file with mode: 0644]
sys/lib/libsa/lookup_elf32.c [new file with mode: 0644]
sys/lib/libsa/lookup_elf64.c [new file with mode: 0644]
sys/lib/libsa/ls.c [new file with mode: 0644]
sys/lib/libsa/lseek.c [new file with mode: 0644]
sys/lib/libsa/minixfs3.c [new file with mode: 0644]
sys/lib/libsa/minixfs3.h [new file with mode: 0644]
sys/lib/libsa/net.c [new file with mode: 0644]
sys/lib/libsa/net.h [new file with mode: 0644]
sys/lib/libsa/netif.c [new file with mode: 0644]
sys/lib/libsa/netif.h [new file with mode: 0644]
sys/lib/libsa/nfs.c [new file with mode: 0644]
sys/lib/libsa/nfs.h [new file with mode: 0644]
sys/lib/libsa/nfsv2.h [new file with mode: 0644]
sys/lib/libsa/nullfs.c [new file with mode: 0644]
sys/lib/libsa/open.c [new file with mode: 0644]
sys/lib/libsa/panic.c [new file with mode: 0644]
sys/lib/libsa/printf.c [new file with mode: 0644]
sys/lib/libsa/qsort.c [new file with mode: 0644]
sys/lib/libsa/rarp.c [new file with mode: 0644]
sys/lib/libsa/read.c [new file with mode: 0644]
sys/lib/libsa/rpc.c [new file with mode: 0644]
sys/lib/libsa/rpc.h [new file with mode: 0644]
sys/lib/libsa/rpcv2.h [new file with mode: 0644]
sys/lib/libsa/saerrno.h [new file with mode: 0644]
sys/lib/libsa/saioctl.h [new file with mode: 0644]
sys/lib/libsa/snprintf.c [new file with mode: 0644]
sys/lib/libsa/sprintf.c [new file with mode: 0644]
sys/lib/libsa/stand.h [new file with mode: 0644]
sys/lib/libsa/stat.c [new file with mode: 0644]
sys/lib/libsa/strerror.c [new file with mode: 0644]
sys/lib/libsa/subr_prf.c [new file with mode: 0644]
sys/lib/libsa/tftp.c [new file with mode: 0644]
sys/lib/libsa/tftp.h [new file with mode: 0644]
sys/lib/libsa/twiddle.c [new file with mode: 0644]
sys/lib/libsa/udp.c [new file with mode: 0644]
sys/lib/libsa/ufs.c [new file with mode: 0644]
sys/lib/libsa/ufs.h [new file with mode: 0644]
sys/lib/libsa/ustarfs.c [new file with mode: 0644]
sys/lib/libsa/ustarfs.h [new file with mode: 0644]
sys/lib/libsa/vsprintf.c [new file with mode: 0644]
sys/lib/libsa/write.c [new file with mode: 0644]
tools/nbsd_ports

index 27ace22c2f89e8a7dd7954f0730e7a8fd2987f9d..5378f2af61c5642cc794f52c87cd63b4e9b04cc4 100644 (file)
@@ -1,4 +1,4 @@
-MAN=   configfile.5 crontab.5 dhcp.conf.5 dir.5 ethers.5 \
+MAN=   boot.cfg.5 configfile.5 crontab.5 dhcp.conf.5 dir.5 ethers.5 \
        fstab.5 hosts.5 httpd.conf.5 http_status.5 keymap.5 \
        passwd.5 resolv.conf.5 resolver.5 rhosts.5 statvfs.5 serv.access.5 \
        system.conf.5 syslog.conf.5 termcap.5 ttytab.5 TZ.5 tzfile.5 utmp.5 \
diff --git a/man/man5/boot.cfg.5 b/man/man5/boot.cfg.5
new file mode 100644 (file)
index 0000000..119ce33
--- /dev/null
@@ -0,0 +1,247 @@
+.\"    $NetBSD: boot.cfg.5,v 1.24 2011/11/28 09:38:45 wiz Exp $
+.\"
+.\" Copyright (c) 2007 Stephen Borrill
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd November 28, 2011
+.Dt BOOT.CFG 5
+.Os
+.Sh NAME
+.Nm boot.cfg
+.Nd configuration file for /boot
+.Sh DESCRIPTION
+The file
+.Pa /boot.cfg
+is used to alter the behaviour of the standard boot loader described in
+.Xr boot 8 .
+Configuration changes include setting the timeout, choosing a console device,
+altering the banner text and displaying a menu allowing boot commands to be
+easily chosen.
+If a
+.Nm
+file is not present, the system will boot as normal.
+.Ss FILE FORMAT
+The format of the file is a series of lines containing keyword/value pairs
+separated by an equals sign
+.Pq Sq = .
+There should be no whitespace surrounding the equals sign.
+Lines beginning with a hash
+.Pq Sq #
+are comments and will be ignored.
+.Pp
+Some keywords can be present multiple times in the file to define additional
+items.
+Such keywords are noted below.
+.Pp
+.Bl -tag -width timeout
+.It Sy banner
+(may be present multiple times)
+The text from banner lines is displayed instead of the standard welcome text
+by the boot loader.
+Up to 10 lines can be defined.
+No special character sequences are recognised, so to specify a blank line, a
+banner line with no value should be given.
+.It Sy clear
+If nonzero, clear the screen before printing the banner.
+If zero, do not clear the screen (the default).
+.It Sy consdev
+Changes the console device to that specified in the value.
+Valid values are any of those that could be specified at the normal boot
+prompt with the consdev command.
+.It Sy default
+Used to specify the default menu item  which will be chosen in the case of
+Return being pressed or the timeout timer reaching zero.
+The value is the number of the menu item as displayed.
+As described above, the menu items are counted from 1 in the order listed in
+.Nm .
+If not specified, the default value will be option 1, i.e. the first item.
+.It Sy format
+Changes how the menu options are displayed.
+Should be set to one of
+.Sq a
+for automatic,
+.Sq l
+for letters and
+.Sq n
+for numbers.
+If set to automatic (the default), menu options will be displayed numerically
+unless there are more than 9 options and the timeout is greater than zero.
+If there are more than 9 options with a timeout greater than zero and
+the format is set to number, only the first 9 options will be available.
+.It Sy load
+Used to load kernel modules, which will be passed on to the kernel for
+initialization during early boot.
+The argument is either the complete path and file name of the module to be
+loaded, or a symbolic module name.
+When the argument is not an absolute path, the boot loader will first
+attempt to load
+.Pa /stand/\*[Lt]machine\*[Gt]/\*[Lt]kernel_version\*[Gt]/modules/\*[Lt]name\*[Gt]/\*[Lt]name\*[Gt].kmod .
+If that file does not exist, it will then attempt to load
+.Pa /\*[Lt]name\*[Gt] .
+May be used as many times as needed.
+.It Sy menu
+(may be present multiple times)
+Used to define a menu item to be displayed to the end-user at boot time
+which allows a series of boot commands to be run without further typing.
+The value consists of the required menu text, followed by a colon
+.Pq Sq \&:
+and then the desired command(s).
+Multiple commands can be specified separated by a semi-colon.
+If the specified menu text is empty
+(the colon appears immediately after the equals sign),
+then the displayed menu text is the same as the command.
+For example:
+.Bd -literal
+menu=Boot normally:boot
+menu=Boot single-user:boot -s
+menu=Boot with module foo:load /foo.kmod;boot
+menu=Boot with serial console:consdev com0;boot
+menu=:boot hd1a:netbsd -as
+.Ed
+.Pp
+Each menu item will be prefixed by an ascending number when displayed,
+i.e. the order in the
+.Nm
+file is important.
+.Pp
+Each command is executed just as though the user had typed it in
+and so can be any valid command that would be accepted at the
+normal boot prompt.
+In addition,
+.Dq Ic prompt
+can be used to drop to the normal boot prompt.
+.It Sy timeout
+If the value is greater than zero, this specifies the time in seconds
+that the boot loader will wait for the end-user to choose a menu item.
+During the countdown period, they may press Return to choose the default
+option or press a number key corresponding to a menu option.
+If any other key is pressed, the countdown will stop and the user will be
+prompted to choose a menu option with no further time limit.
+If the timeout value is set to zero, the default option will be booted
+immediately.
+If the timeout value is negative or is not a number, there will be no
+time limit for the user to choose an option.
+.It Sy userconf
+Passes a
+.Xr userconf 4
+command to the kernel at boot time .
+.It Sy rndseed
+Takes the path to a random-seed file as written by the
+.Fl S
+flag to
+.Xr rndctl 8
+as an argument.
+This file is used to seed the kernel entropy pool
+.Xr rnd 9
+very early in kernel startup, so that high quality randomness is
+available to all kernel modules.
+This argument should be supplied
+before any
+.Dq Ic load
+commands that may load executable modules.
+.El
+.Sh EXAMPLES
+Here is an example
+.Nm
+file:
+.Bd -literal -offset indent
+banner=Welcome to NetBSD
+banner==================
+banner=
+banner=Please choose an option from the following menu:
+menu=Boot normally:boot
+menu=Boot single-user:boot -s
+menu=Boot from second disk:boot hd1a:
+menu=Boot with module foo:load /foo.kmod;boot
+menu=Boot with modules foo and bar:load /foo.kmod;load /bar.kmod;boot
+menu=Boot Xen with 256MB for dom0:load /netbsd-XEN3_DOM0 console=pc;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M
+menu=Boot Xen with 256MB for dom0 (serial):load /netbsd-XEN3_DOM0 console=com0;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M console=com1 com1=115200,8n1
+menu=Boot Xen with dom0 in single-user mode:load /netbsd-XEN3_DOM0 -s;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M
+menu=Go to command line (advanced users only):prompt
+clear=1
+timeout=-1
+default=1
+userconf disable ehci*
+# Always load ramdisk module
+load=/miniroot.kmod
+.Ed
+.Pp
+N.B. Xen counts serial ports from com1 upwards, but
+.Nx
+counts from com0, so the appropriate device name must be used.
+Please see the Xen with serial console example above.
+.Pp
+This will clear the screen and display:
+.Bd -literal -offset indent
+Welcome to NetBSD
+=================
+
+Please choose an option from the following menu:
+
+      1. Boot normally
+      2. Boot single-user
+      3. Boot from second disk
+      4. Boot with module foo
+      5. Boot with modules foo and bar
+      6. Boot Xen with 256 MB for dom0
+      7. Boot Xen with 256 MB for dom0 (serial)
+      8. Boot Xen with dom0 in single-user mode
+      9. Go to command line (advanced users only)
+
+Option [1]:
+.Ed
+.Pp
+It will then wait for the user to type 1, 2, 3, 4, 5, 6, 7, 8 or 9 followed by
+Return.
+Pressing Return by itself will run option 1.
+There will be no timeout.
+.Sh SEE ALSO
+.Xr boot 8 ,
+.Xr boothowto 9
+.Sh HISTORY
+The
+.Nm
+file appeared in
+.Nx 5.0 .
+.Sh AUTHORS
+The
+.Nm
+extensions to
+.Xr boot 8
+were written by
+.An Stephen Borrill
+.Aq sborrill@NetBSD.org .
+.Sh BUGS
+Support for
+.Nm
+is currently for
+.Nx Ns /i386
+and
+.Nx Ns /amd64
+only.
+It is hoped that its use will be extended to other appropriate ports that
+use the
+.Xr boot 8
+interface.
index 6512d10a2ab406339bf2849c893814c66cf283a7..e61c32469a82bf643c9dd007018859867b798559 100644 (file)
-.TH BOOT 8
-.SH NAME
-boot \- from power on to the login prompt
-.SH DESCRIPTION
-.de SP
-.if t .sp 0.4
-.if n .sp
-..
-At power on the machine reads the first sector of the boot device into memory
-and executes it.  This bootstrap code loads
-.BR /boot/boot ,
-the MINIX 3 Boot Monitor.  The monitor loads the kernel binaries from
-.BR /boot/image ,
-or the newest file in
-.B /boot/image
-if it is a directory.
-.PP
-The MINIX 3 system is now running, the different tasks initialize themselves
-and control is transferred to the last one,
-.BR init .
-.PP
-.B Init
-is the grandparent of all MINIX 3 processes, it is responsible for starting
-login processes on each terminal, but first it runs
-.BR /etc/rc .
-.PP
-.B /etc/rc
-checks the state of the system and starts daemons.  First it sets the
-keyboard translation to the mapping in
-.B /etc/keymap
-if present, followed by a call to
-.BR readclock (8)
-to set MINIX 3 time from the hardware clock.  Next the file systems are checked
-if necessary and the
-.B /usr
-file system is mounted.
-.PP
-The system is now ready for multiuser startup,
-.B /etc/rc
-calls
-.B /usr/etc/rc
-that cleans out /tmp, /usr/tmp, and resets or cycles log files by running
-.BR /usr/etc/daily ,
-starts the
-.BR update (8)
+.\"    $NetBSD: boot.8,v 1.58 2011/05/31 03:43:47 uebayasi Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software written and contributed
+.\" to Berkeley by William Jolitz.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)boot_i386.8        8.2 (Berkeley) 4/19/94
+.\"
+.Dd May 26, 2011
+.Dt BOOT 8 i386
+.Os
+.Sh NAME
+.Nm boot
+.Nd
+system bootstrapping procedures
+.Sh DESCRIPTION
+.Tn IA-32
+computers
+.Po
+the
+.Tn IBM PC
+and its clones
+.Pc
+that can run
+.Nx Ns /i386
+can use any of the following boot procedures, depending on what the hardware and
+.Tn BIOS
+support:
+.Pp
+.Bl -tag -width "pxeboot(8)"
+.It boot
+bootstrap
+.Nx
+from the system
+.Tn BIOS
+.It Xr dosboot 8
+bootstrap
+.Nx
+from
+.Tn MS-DOS
+.It Xr w95boot 8
+bootstrap
+.Nx
+from
+.Tn Windows 95
+.It Xr pxeboot 8
+network bootstrap
+.Nx
+from a
+.Tn TCP/IP
+.Tn LAN
+with
+.Tn DHCP ,
+.Tn TFTP ,
 and
-.BR cron (8)
-daemons, and initializes the network services.
-.B /etc/rc
-finally runs
-.BR /usr/local/etc
-to initialize the system in a site or host dependent way.
-.PP
-.B Init
-reads
-.B /etc/ttytab
-and starts a
-.BR getty (8)
-for each enabled terminal line to allow a user to log in.
-.SH OPTIONS
-.TP
-.B bootopts=\-s
-The value of the boot variable
-.B bootopts
-is passed to
-.BR /etc/rc .
-If it contains
-.B \-s
-then the system will run a single user shell before continuing with multiuser
-startup.  (Note that one normally uses
-.B boot \-s
-instead of setting
-.BR bootopts .)
-.TP
-.B bootopts=\-a
-This flag tells that
-.B /etc/fstab
-must be ignored.  The system asks for a device to use as /usr instead.  This
-will also be done if the root device is not as mentioned in
-.BR /etc/fstab .
-.TP
-.B bootopts=\-f
-Force a file system check, even if the system was shut down properly.  (Do
-this once in a while to be sure about the state of the file systems.)
-.TP
-.BI servers= program\fR[,\fIprogram\fR...]
-Names the special servers that must be started in /usr/etc/rc.  The setting
-.BR "servers=inet"
-will start the TCP/IP server.
-.SH "BOOT ENVIRONMENT"
-Many features of the drivers inside the kernel are controlled by settings in
-the boot environmenti, like
-.B bootopts
-above does for
-.BR /etc/rc .
-The values of these variables are usually colon or comma separated
-numbers configuring the driver.
-.B "DPETH0 = 300:10"
-tells the DP ethernet driver to use I/O address 0x300, interrupt request
-10, and the default memory address (0xD0000, values may be omitted) for the
-first ethernet board.  (Note that IRQ 2 is redirected to IRQ 9 on AT's and
-PS/2's, so use 9 if a device is jumpered for 2.)
-.PP
-Variables that are special to both the monitor and the kernel are described
-in
-.BR monitor (8).
-This section lists extra variables or variable settings:
-.TP
-\fBc\fIn\fR = \fBat\fR | \fBbios\fR | \fBesdi\fR | \fBxt\fR | \fBaha1540\fR | \fBdosfile\fR | \fBfatfile\fR
-Choose the driver that is to be used as controller
-.IR n ,
-in order: IBM/AT (classic AT or newer IDE), BIOS (any disk), ESDI
-(some PS/2s), IBM/XT, Adaptec 154x, MINIX 3 under DOS "file as disk",
-FAT file system "file as disk".
-By default
-.B at
-is used on AT bus systems,
-.B bios
-on PS/2s and XTs, and
-.B dosfile
-when running under DOS.
-Most drivers are present in the kernel as distributed, but may be taken out
-by modifying
-.BR /usr/include/minix/config.h .
+.Tn NFS .
+.El
+.Ss Power fail and crash recovery
+Normally, the system will reboot itself at power-up or after crashes.
+An automatic consistency check of the file systems will be performed,
+and unless this fails, the system will resume multi-user operations.
+.Ss Cold starts
+The 386
+.Tn "PC AT"
+clones attempt to boot the floppy disk drive A (otherwise known as drive
+0) first, and failing that, attempt to boot the hard disk C (otherwise
+known as hard disk controller 1, drive 0).
+The
+.Nx
+bootblocks are loaded and started either by the
+.Tn BIOS ,
+or by a boot selector program (such as OS-BS, BOOTEASY, the OS/2 Boot Menu or
+.Nx Ns 's
+.No boot-selecting
+master boot record - see
+.Xr mbr 8 ) .
+.Ss Normal Operation
+Once running, a banner similar to the following will appear:
+.Bd -unfilled -offset indent
+\*[Gt]\*[Gt] NetBSD BIOS Boot, revision 3.0
+\*[Gt]\*[Gt] (user@buildhost, builddate)
+\*[Gt]\*[Gt] Memory: 637/15360 k
+Press return to boot now, any other key for boot menu
+booting hd0a:netbsd - starting in 5
+.Ed
+.Pp
+After a countdown, the system image listed will be loaded.
+In the example above, it will be
+.Dq Li hd0a:netbsd
+which is the file
+.Nm netbsd
+on partition
+.Dq a
+of the
+.Nx
+.Tn MBR
+partition of the first hard disk known to the
+.Tn BIOS
+.Po
+which is an
+.Tn IDE
+or similar device - see the
+.Sx BUGS
+section
+.Pc .
+.Pp
+Pressing a key within the time limit, or before the boot program starts, will
+enter interactive mode.
+When using a short or 0 timeout, it is often useful to interrupt the boot
+by holding down a shift key, as some BIOSes and BIOS extensions will drain the
+keystroke buffer at various points during POST.
+.Pp
+If present, the file
+.Pa /boot.cfg
+will be used to configure the behaviour of the boot loader including
+setting the timeout, choosing a console device, altering the banner
+text and displaying a menu allowing boot commands to be easily chosen.
 See
-.BR controller (4).
-(An XT should always use the BIOS driver, not the XT driver, because BIOS
-calls are cheap on an XT.  The XT driver can be used on AT machines with an
-old XT controller.)
-.TP
-\fBDPETH\fIn\fR = \fBon\fR | \fBoff\fR
-Turn an ethernet board on or off.  The driver is by default in "sink" mode
-for all boards.  The sink mode allows one to use the driver without an
-ethernet board installed.  The driver will play /dev/null for that device,
-i.e. nothing comes in, and anything send out is dropped on the floor.  If
-the board is turned on then the driver will use it to send out packets, if
-it is turned off then the driver will fail for that board.
-.PP
-.if n .ta \w'DPETHn = I/O-addr:irq:mem_addr:mem_size'u+2m
-.if t .ta \w'\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fImem_addr\fR:\fImem_size\fR'u+2m
-\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fImem_addr\fR:\fImem_size\fR       (WD80x3)
-.br
-\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fB0\fR     (NE2000)
-.br
-\fBDPETH\fIn\fR = \fII/O-addr\fR:\fIirq\fR:\fIflags\fR (3c503)
-.RS
-Set the I/O address (hex), IRQ (decimal), memory address (hex), memory
-size (hex), or flags (hex) of the
-.IR n -th
-ethernet board and turn it on.  By default they are configured as
-280:3:D0000 and 300:5:C8000 with the memory size set to 2000, 4000, or 8000
-depending on the type of board found.
-For the Western Digital cards the IRQ must be what the board expects,
-but the memory address is programmed into the board by the driver.
-The SMC EtherEZ board, a WD8013 successor, has only 8K
-memory.  This confuses the driver, so you need to explicitly specify the
-board size as being 2000.
-The memory address and size have no meaning for the Novell ethernet boards,
-but the address may be explicitly set to zero to indicate that the board
-.B is
-a Novell ethernet board.
-For the 3Com 3c503 the third parameter are flags, with the low bit indicates
-that the on-board tranceiver must be used if 0 (thin ethernet), or that an
-external tranceiver is used on the AUI port if set to 1.
-The IRQ is software settable, and must be specified as 2 (XT), 3, 4, 5,
-or 9 (AT).  The memory address is set on the board by jumpers.  The driver
-does not support I/O mode for the 3c503.
-(Note the little differences between board types.  For the 8003/8013 and
-NE1000/NE2000 the IRQ is fixed and the memory address variable, for the
-3c503 the IRQ is variable and the memory address is fixed, but need not be
-specified.  Messy.)
-.RE
-.TP
-\fBDPETH\fIn\fB_EA\fR = \fIe0\fR:\fIe1\fR:\fIe2\fR:\fIe3\fR:\fIe4\fR:\fIe5\fR
-Set the ethernet address of the
-.IR n -th
-ethernet board.  The address is normally obtained from the ethernet board,
-so only in exceptional circumstances is this setting ever needed.  (Use the
-address of the main server if you want a career change.)
-.TP
-\fBAHA0\fR = \fII/O-addr\fR:\fIbus-on\fR:\fIbus-off\fR:\fItr-speed\fR
-Configure the Adaptec 154xA SCSI host adapter to use the given I/O address
-(hex), Bus-on time (decimal), Bus-off time (decimal) and transfer speed
-(hex).  The default is 330:15:1:00.  The default transfer speed is always
-5.0 Mb/s (code 00) ignoring the jumper settings.
-.TP
-\fBaha1540-d\fIn\fR = \fIsleep-time\fR:\fItarget\fR,\fIlun\fR
-Program SCSI disk
-.I n
-to have the given target and logical unit number.  The target and lun
-of a tape or other SCSI device may be changed by setting the
-.BI aha1540-d n
-variable that would be used had it been a disk.  So tape device c0t7 can be
-set to target 4, lun 1 with aha1540-d7=:4,1.
-(The
-.I sleep-time
-parameter is present but ignored to be compatible with Minix-vmd.)
-.TP
-\fBdosfile-d\fIn\fR = \fIfile\fR
-Tells the DOS virtual disk driver for disk
-.I n
-to use a given file as a disk.  The file is a DOS file name that the
-boot monitor must be able to open.
-.TP
-\fBfatfile-d\fIn\fR = \fIdriver:minor:file\fR
-Tells the FAT virtual disk driver for disk
-.I n
-to use a given file as a disk.  The
-.I driver
-parameter is the name of driver that handles the disk, and
-.I minor
-is the device number of the partition where the file is found.  See
-.BR controller (4)
-for names and numbers.
+.Xr boot.cfg 5 .
+.Pp
 The
-.I file
-argument is the path to the file from the root directory down.  The driver
-named must also be tied to a controller with a
-.BI c n
-variable, so that the FAT file driver can find it.
-A handy way to find the proper minor number is to run
-.B "ls\ \-l"
-on the device where the file is found.  As a example, we assume the most
-common situation of a disk file on the first partition of the first drive
-on an ATA (IDE) controller:
-.SP
-.in +5
-.ft B
-.nf
-c0 = fatfile
-c1 = at
-fatfile-d0 = at:1:/minix/minix.mnx
-.fi
-.ft P
-.in -5
-.TP
-.BR TZ " = " GMT0
-This sets the time zone the hardware clock is running in.
-.B Readclock
-uses this to correctly obtain the time of the clock.  The timezone of the
-system is set in
-.BR /etc/profile .
-This boot variable is normally not set, only a few UNIX die-hards who
-don't care about the time Windows sees and don't want to change the clock
-twice a year for daylight savings use this option.  (Set Windows time to the
-time zone of Casablanca to match.)
-.SH "TCP/IP CONFIGURATION"
-To use TCP/IP you need to run the
-.B inet
-server, and unless you are running standalone you have to enable the
-ethernet driver.  See the
-.B servers
+.Nx Ns /i386
+boot loader can boot a kernel using either the native
+.Nx
+boot protocol, or the
+.Dq multiboot
+protocol (which is compatible with some other operating systems).
+In the native
+.Nx
+boot protocol, options are passed from the boot loader
+to the kernel via flag bits in the
+.Va boothowto
+variable (see
+.Xr boothowto 9 ) .
+In the multiboot protocol, options are passed from the boot loader
+to the kernel as strings.
+.Ss Diagnostic Output
+If the first stage boot fails to load the boot, it will print a terse
+message indicating the reason for the failure.
+The possible error messages and their cause are listed in
+.Xr mbr 8 .
+.Pp
+If the first stage boot succeeds, the banner will be shown and the
+error messages should be self-explanatory.
+.Ss Interactive mode
+In interactive mode, the boot loader will present a prompt, allowing
+input of these commands:
+.\" NOTE: much of this text is duplicated in the MI boot.8.
+.\" Some of it is
+.\" also duplicated in the i386-specific dosboot.8 and pxeboot.8;
+.\" please try to keep all relevant files synchronized.
+.Bl -tag -width 04n -offset 04n
+.It Ic boot Oo Va device : Ns Oc Oo Va filename Oc Oo Fl 1234abcdmqsvxz Oc
+The default
+.Va device
+will be set to the disk that the boot loader was
+loaded from.
+To boot from an alternate disk, the full name of the device should
+be given at the prompt.
+.Va device
+is of the form
+.Xo Va xd
+.Op Va N Ns Op Va x
+.Xc
+where
+.Va xd
+is the device from which to boot,
+.Va N
+is the unit number, and
+.Va x
+is the partition letter.
+.Pp
+The following list of supported devices may vary from installation to
+installation:
+.Pp
+.Bl -hang -compact
+.It hd
+Hard disks as numbered by the BIOS.
+This includes ST506, IDE, ESDI, RLL disks on a WD100[2367] or
+lookalike controller(s), and SCSI disks
+on SCSI controllers recognized by the BIOS.
+.It fd
+Floppy drives as numbered by the BIOS.
+.El
+.Pp
+The default
+.Va filename
+is
+.Pa netbsd ;
+if the boot loader fails to successfully
+open that image, it then tries
+.Pa netbsd.gz
+(expected to be a kernel image compressed by gzip), followed by
+.Pa netbsd.old ,
+.Pa netbsd.old.gz ,
+.Pa onetbsd ,
+and finally
+.Pa onetbsd.gz .
+Alternate system images can be loaded by just specifying the name of the image.
+.Pp
+Options are:
+.Bl -tag -width xxx
+.It Fl 1
+Sets the machine-dependent flag
+.Sy RB_MD1
+in
+.Va boothowto .
+In
+.Nx Ns /i386 ,
+this disables multiprocessor boot;
+the kernel will boot in uniprocessor mode.
+.It Fl 2
+Sets the machine-dependent flag
+.Sy RB_MD2
+in
+.Va boothowto .
+In
+.Nx Ns /i386 ,
+this disables ACPI.
+.It Fl 3
+Sets the machine-dependent flag
+.Sy RB_MD3
+in
+.Va boothowto .
+In
+.Nx Ns /i386 ,
+this has no effect.
+.It Fl 4
+Sets the machine-dependent flag
+.Sy RB_MD4
+in
+.Va boothowto .
+In
+.Nx Ns /i386 ,
+this has no effect.
+.It Fl a
+Sets the
+.Sy RB_ASKNAME
+flag in
+.Va boothowto .
+This causes the kernel to prompt for the root file system device,
+the system crash dump device, and the path to
+.Xr init 8 .
+.It Fl b
+Sets the
+.Sy RB_HALT
+flag in
+.Va boothowto .
+This causes subsequent reboot attempts to halt instead of rebooting.
+.It Fl c
+Sets the
+.Sy RB_USERCONF
+flag in
+.Va boothowto .
+This causes the kernel to enter the
+.Xr userconf 4
+device configuration manager as soon as possible during the boot.
+.Xr userconf 4
+allows devices to be enabled or disabled, and allows device locators
+(such as hardware addresses or bus numbers)
+to be modified before the kernel attempts to attach the devices.
+.It Fl d
+Sets the
+.Sy RB_KDB
+flag in
+.Va boothowto .
+Requests the kernel to enter debug mode, in which it
+waits for a connection from a kernel debugger; see
+.Xr ddb 4 .
+.It Fl m
+Sets the
+.Sy RB_MINIROOT
+flag in
+.Va boothowto .
+Informs the kernel that a mini-root file system is present in memory.
+.It Fl q
+Sets the
+.Sy AB_QUIET
+flag in
+.Va boothowto .
+Boot the system in quiet mode.
+.It Fl s
+Sets the
+.Sy RB_SINGLE
+flag in
+.Va boothowto .
+Boot the system in single-user mode.
+.It Fl v
+Sets the
+.Sy AB_VERBOSE
+flag in
+.Va boothowto .
+Boot the system in verbose mode.
+.It Fl x
+Sets the
+.Sy AB_DEBUG
+flag in
+.Va boothowto .
+Boot the system with debug messages enabled.
+.It Fl z
+Sets the
+.Sy AB_SILENT
+flag in
+.Va boothowto .
+Boot the system in silent mode.
+.El
+.It Ic consdev Va dev
+Immediately switch the console to the specified device
+.Va dev
+and reprint the banner.
+.Va dev
+must be one of
+.\" .Bl -item -width com[0123]kbd -offset indent -compact
+.Ar pc , com0 , com1 , com2 ,
+.Ar com3 , com0kbd , com1kbd , com2kbd ,
+.Ar com3kbd ,
+or
+.Ar auto .
+See
+.Sx Console Selection Policy
+in
+.Xr boot_console 8 .
+.It Ic dev Op Va device
+Set the default drive and partition for subsequent filesystem
+operations.
+Without an argument, print the current setting.
+.Va device
+is of the form specified in
+.Cm boot .
+.It Ic help
+Print an overview about commands and arguments.
+.It Ic load Va module Op Ar arguments
+Load the specified kernel
+.Va module ,
+and pass it the specified
+.Ar arguments .
+If the module name is not an absolute path,
+.Pa /stand/ Xo Ns
+.Aq Sy arch Ns
+.Pa / Ns
+.Aq Sy osversion Ns
+.Pa /modules/ Ns
+.Aq Sy module Ns
+.Pa / Ns
+.Aq Sy module Ns
+.Pa .kmod
+.Xc
+is used.
+Possible used of the
+.Ic load
+command include loading a memory disk image before booting a kernel,
+or loading a
+.Tn Xen
+DOM0 kernel before booting the
+.Tn Xen
+hypervisor.
+See
+.Xr boot.cfg 5
+for examples.
+.Pp
+In addition to the
+.Cm boot
+options specified above, the DOM0 kernel accepts
+.Po Ar arguments
+being separated with spaces
+.Pc :
+.Bl -tag -width xxx
+.It Ic bootdev Ns = Ns Ar dev Po or Ic root Ns = Ns Ar dev Pc
+Override the default boot device.
+.Ar dev
+can be a unit name
+.Po Dq wd0
+.Pc ,
+or an interface name
+.Po Dq bge0 ,
+.Dq wm0 ,
+.Ns ...
+.Pc ,
+for cases where the root file system has to be loaded
+from network (see the
+.Sx BUGS
+section in
+.Xr pxeboot 8 ) .
+.It Ic console Ns = Ns Ar dev
+Console used by DOM0 kernel during boot.
+.Ar dev
+accepts the same values as the ones given for the
+.Cm consdev
+command.
+See
+.Sx Console Selection Policy
+in
+.Xr boot_console 8 .
+.It Xo Ic ip Ns = Ns
+.Ar my_ip Ns : Ns Ar serv_ip Ns : Ns Ar gw_ip Ns : Ns
+.Ar mask Ns : Ns Ar host Ns : Ns Ar iface
+.Xc
+Specify various parameters for a network boot (IPs are in
+dot notation),
+each one separated by a colon:
+.Bl -tag -width xxxxxxx
+.It Va my_ip
+address of the host
+.It Va serv_ip
+address of the NFS server
+.It Va gw_ip
+address of the gateway
+.It Va mask
+network mask
+.It Va host
+address of the host
+.It Va iface
+interface
+.Po e.g. Dq xennet0
+or
+.Dq eth0
+.Pc
+.El
+.It Ic nfsroot Ns = Ns Ar address Ns : Ns Ar rootpath
+Boot the system with root on NFS.
+.Ar address
+is the address of the NFS server, and
+.Ar rootpath
+is the remote mount point for the root file system.
+.It Ic pciback.hide Ns = Ns Ar pcidevs
+Pass a list of PCI IDs for use with the PCI backend driver,
+.Xr pciback 4 .
+.Ar pcidevs
+is formed of multiple IDs (in bus:device.function notation),
+each ID being surrounded with brackets.
+PCI domain IDs are currently ignored.
+See
+.Xr pciback 4 .
+.El
+.It Ic ls Op Pa path
+Print a directory listing of
+.Pa path ,
+containing inode number, filename, and file type.
+.Pa path
+can contain a device specification.
+.It Ic modules Bro Ar on | off | enabled | disabled Brc
+The values
+.Ar enabled , on
+will enable module loading for
+.Cm boot
 and
-.BI DPETH n
-boot variables above.  The driver supports these ethernet cards:  Western
-Digital 8003, Western Digital 8013, SMC Elite Ultra 16,
-Novell NE1000 and NE2000, 3Com Etherlink II (3c503).  Many newer
-variants of the WD8013, now under the SMC brand, may also work.
-A common PCI reimplementation of the NE2000 using the Realtek 80 chipset is
-also supported.  Make sure it's just a 10 mbit device and that it has a
-chip marked "RTL 8029".
-.PP
-You are likely to use TCP/IP in one of three situations:
-.PP
-.RS
-Standalone with no connection to a network.
-.SP
-In a small network with no support from a "big" host.
-.SP
-Connected to a large network with address and name servers.
-.RE
-.PP
-In each situation you need a different set of configuration files.
-.SS Standalone
-All you need is a name and an IP address.  Suppose the name is "flotsam"
-and the IP address is 192.168.0.1 from the private IP space, then this is
-put in
-.BR /etc/hosts :
-.PP
-.RS
-.ta +\w'192.168.0.1'u+3n
-192.168.0.1    flotsam
-.RE
-.PP
-And this in
-.BR /etc/dhcp.conf :
-.PP
-.RS
-.nf
-host 192.168.0.0/24 {};
-interface ip0 flotsam;
-.fi
-.RE
-.SS "Small Network"
-A network requires an ethernet driver.  You need to enable one in
-<minix/config.h> and you need to tell
-.B inet
-that it should use that driver by making
-.B /etc/inet.conf
-look like this:
-.PP
-.RS
-.nf
-eth0 DP8390 0 { default; };
-.fi
-.RE
-.PP
-The second word (DP8390) must the name of the ethernet driver you've enabled.
-It can also be seen among the drivers in the output of
-.BR "ps ax" .
-See also
-.BR inet (8).
-.PP
-In a small network there may not be a DHCP server for MINIX 3 to obtain its IP
-address and name from, so you need specify the ethernet address of your machine
-and host names of all machines in the hosts and DHCP configuration files.
-Suppose your machine is to be named "flotsam", and another machine in the
-network is named "jetsam", and let's use network 192.168.0.0/24 again.  The
-file
-.B /etc/hosts
-now looks like this:
-.PP
-.RS
-.ta +\w'192.168.0.1'u+3n
-.nf
-192.168.0.1    flotsam
-192.168.0.2    jetsam
-.fi
-.RE
-.PP
-And
-.B /etc/dhcp.conf
-like this:
-.PP
-.RS
-.nf
-host 192.168.0.0/24 {};
-client 0:1:1b:a:68:ce flotsam;
-.fi
-.RE
-.PP
-Use
-.B hostaddr \-e
-to find out what the ethernet address of your network card is.  (The address
-above is an example.)
-.PP
-A host needs to have all hostnames used on your little network in its
-host file.  In the DHCP configuration you only need the client entry of the
-system itself, but it may be useful to add all client entries to make them all
-the same.
-.PP
-If one of the machines is always on when any of the others is, then you can let
-it be a DHCP server.  The other machines don't need a hosts or DHCP file
-anymore.  If flotsam is the server then its
-.BR /etc/dhcp.conf
-looks like this:
-.PP
-.RS
-.nf
-.ta +4m
-host 192.168.0.0/24 {
-       DNSserver flotsam;
-};
-client 0:1:1b:a:68:ce flotsam { option server; };
-client 0:0:c0:3a:12:10 jetsam;
-.fi
-.RE
-.SS "Large Network"
-In a network with a central network administration your machine's IP address
-and name are given by the DHCP server.  You don't need any configuration
-files.  If you want your machine to do more, like being a router or
-something, then see
-.BR inet (8)
-on setting up more than one network interface.
-.PP
-.SS "Simpler configuration tools"
+.Cm multiboot ,
+whereas
+.Ar disabled , off
+will turn off the feature.
+.It Ic multiboot Va kernel Op Ar arguments
+Boot the specified
+.Va kernel ,
+using the
+.Dq multiboot
+protocol instead of the native
+.Nx
+boot protocol.
 The
-.BR dhcpd
-and
-.BR nonamed
-daemons are complex little programs that try to obtain information about
-their surroundings automatically to tell the machine what its place in the
-network is.  It should come as no surprise that there are simpler utilities
-to configure a machine.  On a memory starved machine it may even be wise to
-configure a machine statically to get rid of the daemons.  The first daemon,
-.BR dhcpd ,
-can be replaced by:
-.PP
-.RS
-.B ifconfig \-h
-.I host-IP-address
-.B \-n
-.I netmask
-.br
-.B add_route \-g
-.I gateway-IP-address
-.RE
-.PP
-to set the IP address and netmask of the machine.  Note that you can only
-do this if the machine has a static IP address, or chaos will follow.  Remove
-.BR /usr/adm/dhcp.cache
-if the DHCP daemon has run before.
-.PP
-The name daemon,
-.BR nonamed ,
-can be replaced by an entry in
-.B /etc/resolv.conf
-that specifies an external name daemon:
-.PP
-.RS
-.B nameserver
-.I nameserver-IP-address
-.RE
-.PP
+.Va kernel
+is specified in the same way as with the
+.Ic boot
+command.
+.Pp
+The multiboot protocol may be used in the following cases:
+.Bl -tag -width indent
+.It Nx Ns / Ns  Xen No kernels
+The
+.Tn Xen
+DOM0 kernel must be loaded as a module using the
+.Ic load
+command, and the
+.Tn Xen
+hypervisor must be booted using the
+.Ic multiboot
+command.
+Options for the DOM0 kernel (such as
+.Dq -s
+for single user mode) must be passed as options to the
+.Ic load
+command.
+Options for the hypervisor (such as
+.Dq dom0_mem=256M
+to reserve 256 MB of memory for DOM0)
+must be passed as options to the
+.Ic multiboot
+command.
+See
+.Xr boot.cfg 5
+for examples on how to boot
+.Nx Ns / Ns  Xen.
+.It Nx No multiboot kernels
+A
+.Nx
+kernel that was built with
+.Cd options MULTIBOOT
+(see
+.Xr multiboot 8 )
+may be booted with either the
+.Ic boot
+or
+.Ic multiboot
+command, passing the same
+.Ar arguments
+in either case.
+.It Non- Ns Nx No kernels
+A kernel for a
+.No non- Ns Nx
+operating system that expects to be booted using the
+multiboot protocol (such as by the GNU
+.Dq GRUB
+boot loader)
+may be booted using the
+.Ic multiboot
+command.
+See the foreign operating system's documentation for the available
+.Ar arguments .
+.El
+.It Ic quit
+Reboot the system.
+.It Ic userconf Va command
+Pass the
+.Va command
+to
+.Xr userconf 4
+at boot time .
+These commands are processed before the interactive
+.Xr userconf 4
+shell is executed, if requested .
+.It Ic vesa Bro Va modenum | Ar on | off | enabled | disabled | list Brc
+Initialise the video card to the specified resolution and bit depth.
 The
-.B ifconfig
+.Va modenum
+should be in the form of
+.Ar 0x100 , 800x600 , 800x600x32 .
+The values
+.Ar enabled , on
+put the display into the default mode, and
+.Ar disabled , off
+returns the display into standard vga mode.
+The value
+.Ar list
+lists all supported modes.
+.El
+.Pp
+In an emergency, the bootstrap methods described in the
+.Nx
+installation notes for the i386 architecture
+can be used to boot from floppy or other media,
+or over the network.
+.Sh FILES
+.Bl -tag -width /usr/mdec/bootxx_fstype -compact
+.It Pa /boot
+boot program code loaded by the primary bootstrap
+.It Pa /boot.cfg
+optional configuration file
+.It Pa /netbsd
+system code
+.It Pa /netbsd.gz
+gzip-compressed system code
+.It Pa /usr/mdec/boot
+master copy of the boot program (copy to /boot)
+.It Pa /usr/mdec/bootxx_fstype
+primary bootstrap for filesystem type fstype, copied to the start of
+the
+.Nx
+partition by
+.Xr installboot 8 .
+.El
+.Sh SEE ALSO
+.Xr ddb 4 ,
+.Xr pciback 4 ,
+.Xr userconf 4 ,
+.Xr boot.cfg 5 ,
+.Xr boot_console 8 ,
+.Xr dosboot 8 ,
+.Xr halt 8 ,
+.Xr installboot 8 ,
+.Xr mbr 8 ,
+.Xr multiboot 8 ,
+.Xr pxeboot 8 ,
+.Xr reboot 8 ,
+.Xr shutdown 8 ,
+.Xr w95boot 8 ,
+.Xr boothowto 9
+.Sh BUGS
+The kernel file name must be specified before, not after, the boot options.
+Any
+.Ar filename
+specified after the boot options, e.g.:
+.Pp
+.Bd -unfilled -offset indent -compact
+.Cm boot -d netbsd.test
+.Ed
+.Pp
+is ignored, and the default kernel is booted.
+.Pp
+Hard disks are always accessed by
+.Tn BIOS
+functions.
+Unit numbers are
+.Tn BIOS
+device numbers which might differ from numbering in the
+.Nx
+kernel or physical parameters
+.Po
+e.g.,
+.Tn SCSI
+slave numbers
+.Pc .
+There isn't any distinction between
+.Dq sd
 and
-.B add_route
-calls can be placed in the file
-.BR /etc/rc.net .
-Check
-.B /usr/etc/rc
-to see how
-.BR /etc/rc.net
-can be used to override running the normal series of network deamons.
-Note that
-.BR /etc/rc.net
-is sourced, so you can use the same variables and functions that
-.BR /usr/etc/rc
-uses.
-These changes undo all the efforts to make MINIX 3 TCP/IP
-autoconfigurable.  Make very sure that all the IP addresses are correct, and
-that the IP address of your machine is unique.  (Mistakenly using the
-address of a main server will make all other machines look at your machine,
-and will make all the users of all other machines look at you.)
-.SH FILES
-.TP 20n
-/boot
-MINIX 3 Boot Monitor.
-.TP
-/minix
-Kernel image, or directory containing them.
-.TP
-/etc/rc
-Basic system initialization.
-.TP
-/usr/etc/rc
-Complete system initialization.
-.TP
-/etc/rc.net
-Specialized network initialization.
-.TP
-/usr/local/etc/rc
-Per site initialization.
-.TP
-/etc/hosts
-Name to IP address mapping.
-.TP
-/etc/dhcp.conf
-Network initialization.
-.TP
-/etc/resolv.conf
-Name resolver configuration.
-.SH "SEE ALSO"
-.BR monitor (8),
-.BR init (8),
-.BR inet (8),
-.BR loadkeys (8),
-.BR readclock (8),
-.BR fsck (1),
-.BR fstab (5),
-.BR update (8),
-.BR cron (8),
-.BR ttytab (5),
-.BR getty (8),
-.BR hostaddr (1),
-.BR ifconfig (8),
-.BR dhcpd (8),
-.BR nonamed (8),
-.BR tcpd (8),
-.BR hosts (5),
-.BR ethers (5),
-.BR resolv.conf (5),
-.BR inet (8).
-.SH DIAGNOSTICS
-.TP 5n
-Checking File Systems.
-If the system has crashed then
-.B fsck
-is called for the root and /usr file systems.  It is wise to reboot if the
-root file system must be fixed.
-.TP
-Finish the name of device to mount as /usr: /dev/
-The prompt for the
-.B \-a
-option, or if the name of the /usr file system has not been set in /etc/fstab.
-You can type a device name, say
-.BR fd0 .
-.TP
-Unable to obtain an IP address after 10 seconds.
-TCP/IP misconfiguration.  The DHCP daemon may have failed because the ethernet
-address of the machine is not known to the DHCP server, the DHCP
-configuration is not filled in properly, or the DHCP server can not be reached.
-Either talk to your Network Administrator, or make a dhcp.conf
-and a hosts file.
-.TP
-1.2.3.4 login:
-If you see an IP address instead of a host name then the system failed to
-translate the IP address.  Either talk to your Network Administrator to
-have the reverse address translation tables fixed, or make a hosts file.
-.SH NOTES
-The 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 networks can be used for
-private networks.  (This so-called CIDR notation names an IP address and
-the number of bits in the network number.  So 172.16.0.0/12 includes all
-addresses from 172.16.0.0 to 172.31.255.255.)
-RFC-1597 will tell you why private networks are good, and RFC-1627 why
-they are bad.
-.SH BUGS
-Indefinite hangs are possible if I/O addresses or IRQ's are wrong.  A driver
-may babble about addresses and IRQ's, but that does not mean that what it
-says is true, it may just be configured that way.  It is very difficult to
-find peripherals on a PC automatically, and MINIX 3 doesn't even try.
-.SH AUTHOR
-Kees J. Bot <kjb@cs.vu.nl>
+.Dq wd
+devices at the bootloader level.
+This is less a bug of the bootloader code than
+a shortcoming of the PC architecture.
+The default disk device's name printed in the starting message
+is derived from the
+.Dq type
+field of the
+.Nx
+disklabel (if it is a hard disk).
diff --git a/sys/arch/i386/stand/boot/Makefile b/sys/arch/i386/stand/boot/Makefile
new file mode 100644 (file)
index 0000000..7334e22
--- /dev/null
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile,v 1.8 2010/05/27 06:58:13 dholland Exp $
+
+SUBDIR= biosboot
+
+LIBOBJ= ${.OBJDIR}
+.MAKEOVERRIDES+= LIBOBJ
+
+.include <bsd.subdir.mk>
+.include <bsd.obj.mk>
+
+cleandir distclean: .WAIT cleanlibdir
+
+cleanlibdir:
+       -rm -rf lib
diff --git a/sys/arch/i386/stand/boot/Makefile.boot b/sys/arch/i386/stand/boot/Makefile.boot
new file mode 100644 (file)
index 0000000..c6b4d7c
--- /dev/null
@@ -0,0 +1,171 @@
+# $NetBSD: Makefile.boot,v 1.56 2011/12/25 06:09:09 tsutsui Exp $
+
+S=     ${.CURDIR}/../../../../..
+
+NOMAN=
+PROG?= boot
+NEWVERSWHAT?= "BIOS Boot"
+VERSIONFILE?= ${.CURDIR}/../version
+
+AFLAGS.biosboot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+
+SOURCES?= biosboot.S boot2.c conf.c devopen.c exec.c
+SRCS= ${SOURCES}
+.if !make(depend)
+SRCS+= vers.c
+.endif
+
+PIE_CFLAGS=
+PIE_AFLAGS=
+PIE_LDFLAGS=
+
+.include <bsd.own.mk>
+
+STRIPFLAG=     # nothing
+
+LIBCRT0=       # nothing
+LIBCRTBEGIN=   # nothing
+LIBCRTEND=     # nothing
+LIBC=          # nothing
+
+BINDIR=/usr/mdec
+BINMODE=444
+
+.PATH: ${.CURDIR}/.. ${.CURDIR}/../../lib
+
+LDFLAGS+= -nostdlib -Wl,-N -Wl,-e,boot_start
+CPPFLAGS+= -I ${.CURDIR}/..  -I ${.CURDIR}/../../lib -I ${S}/lib/libsa
+CPPFLAGS+= -I ${.OBJDIR}
+# Make sure we override any optimization options specified by the user
+COPTS=  -Os
+
+.if defined(HAVE_GCC)
+.if ${MACHINE_ARCH} == "x86_64"
+LDFLAGS+=  -Wl,-m,elf_i386
+AFLAGS+=   -m32
+CPUFLAGS=  -m32
+LIBKERN_ARCH=i386
+KERNMISCMAKEFLAGS="LIBKERN_ARCH=i386"
+.else
+CPUFLAGS=  -march=i386 -mtune=i386
+.endif
+.endif
+
+CFLAGS+=   -mno-sse -mno-sse2 -mno-sse3
+
+COPTS+=    -ffreestanding
+CFLAGS+= -Wall -Wmissing-prototypes -Wstrict-prototypes
+CPPFLAGS+= -nostdinc -D_STANDALONE
+CPPFLAGS+= -I$S
+
+CPPFLAGS+= -DSUPPORT_PS2
+CPPFLAGS+= -DDIRECT_SERIAL
+CPPFLAGS+= -DSUPPORT_SERIAL=boot_params.bp_consdev
+
+CPPFLAGS+= -DCONSPEED=boot_params.bp_conspeed
+CPPFLAGS+= -DCONSADDR=boot_params.bp_consaddr
+CPPFLAGS+= -DCONSOLE_KEYMAP=boot_params.bp_keymap
+
+CPPFLAGS+= -DSUPPORT_CD9660
+CPPFLAGS+= -DSUPPORT_USTARFS
+CPPFLAGS+= -DSUPPORT_DOSFS
+CPPFLAGS+= -DSUPPORT_EXT2FS
+CPPFLAGS+= -DSUPPORT_MINIXFS3
+CPPFLAGS+= -DPASS_BIOSGEOM
+CPPFLAGS+= -DPASS_MEMMAP
+#CPPFLAGS+= -DBOOTPASSWD
+CPPFLAGS+= -DEPIA_HACK
+#CPPFLAGS+= -DDEBUG_MEMSIZE
+#CPPFLAGS+= -DBOOT_MSG_COM0
+CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
+
+# The biosboot code is linked to 'virtual' address of zero and is
+# loaded at physical address 0x10000.
+# XXX The heap values should be determined from _end.
+SAMISCCPPFLAGS+= -DHEAP_START=0x40000 -DHEAP_LIMIT=0x70000
+SAMISCCPPFLAGS+= -DLIBSA_PRINTF_LONGLONG_SUPPORT
+SAMISCMAKEFLAGS+= SA_USE_CREAD=yes     # Read compressed kernels
+SAMISCMAKEFLAGS+= SA_INCLUDE_NET=no    # Netboot via TFTP, NFS
+
+.if defined(HAVE_GCC) || defined(HAVE_PCC)
+CPPFLAGS+=     -Wno-pointer-sign
+.endif
+
+# CPPFLAGS+= -DBOOTXX_RAID1_SUPPORT
+
+I386_STAND_DIR?= $S/arch/i386/stand
+
+CLEANFILES+= machine x86
+
+.if !make(obj) && !make(clean) && !make(cleandir)
+.BEGIN:
+       -rm -f machine && ln -s $S/arch/i386/include machine
+       -rm -f x86 && ln -s $S/arch/x86/include x86
+.ifdef LIBOBJ
+       -rm -f lib && ln -s ${LIBOBJ}/lib lib
+       mkdir -p ${LIBOBJ}/lib
+.endif
+.endif
+
+### find out what to use for libi386
+I386DIR= ${I386_STAND_DIR}/lib
+.include "${I386DIR}/Makefile.inc"
+LIBI386= ${I386LIB}
+
+### find out what to use for libsa
+SA_AS= library
+SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
+.include "${S}/lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+### find out what to use for libkern
+KERN_AS= library
+.include "${S}/lib/libkern/Makefile.inc"
+LIBKERN= ${KERNLIB}
+
+### find out what to use for libz
+Z_AS= library
+.include "${S}/lib/libz/Makefile.inc"
+LIBZ= ${ZLIB}
+
+
+cleandir distclean: .WAIT cleanlibdir
+
+cleanlibdir:
+       -rm -rf lib
+
+LIBLIST= ${LIBI386} ${LIBSA} ${LIBZ} ${LIBKERN} ${LIBI386} ${LIBSA}
+# LIBLIST= ${LIBSA} ${LIBKERN} ${LIBI386} ${LIBSA} ${LIBZ} ${LIBKERN}
+
+CLEANFILES+= ${PROG}.tmp ${PROG}.map ${PROG}.syms vers.c
+
+vers.c: ${VERSIONFILE} ${SOURCES} ${LIBLIST} ${.CURDIR}/../Makefile.boot
+       ${HOST_SH} ${S}/conf/newvers_stand.sh ${VERSIONFILE} x86 ${NEWVERSWHAT}
+
+# Anything that calls 'real_to_prot' must have a %pc < 0x10000.
+# We link the program, find the callers (all in libi386), then
+# explicitly pull in the required objects before any other library code.
+${PROG}: ${OBJS} ${LIBLIST} ${.CURDIR}/../Makefile.boot
+       ${_MKTARGET_LINK}
+       bb="$$( ${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,0 -Wl,-cref \
+           ${OBJS} ${LIBLIST} | ( \
+               while read symbol file; do \
+                       [ -z "$$file" ] && continue; \
+                       [ "$$symbol" = real_to_prot ] && break; \
+               done; \
+               while \
+                       oifs="$$IFS"; \
+                       IFS='()'; \
+                       set -- $$file; \
+                       IFS="$$oifs"; \
+                       [ -n "$$2" ] && echo "${I386DST}/$$2"; \
+                       read file rest && [ -z "$$rest" ]; \
+               do :; \
+               done; \
+       ) )"; \
+       ${CC} -o ${PROG}.syms ${LDFLAGS} -Wl,-Ttext,0 \
+               -Wl,-Map,${PROG}.map -Wl,-cref ${OBJS} $$bb ${LIBLIST}
+       ${OBJCOPY} -O binary ${PROG}.syms ${PROG}
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/i386/stand/boot/biosboot.S b/sys/arch/i386/stand/boot/biosboot.S
new file mode 100644 (file)
index 0000000..0c3033c
--- /dev/null
@@ -0,0 +1,149 @@
+/*     $NetBSD: biosboot.S,v 1.8 2011/01/05 23:13:01 jakllsch Exp $    */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <sys/bootblock.h>
+
+/*
+ * Code linked to 0x1000:0 and (usually) read from /boot by bootxx code
+ *
+ * On entry:
+ *     %dl                     BIOS drive number
+ *     %ecx:%ebx               Sector number of NetBSD partition
+ *     %ds:%si                 Boot parameter block (patched by installboot)
+ *     %cs                     0x1000
+ *     %ds, %es, %ss           All zero
+ *     %sp                     near 0xfffc
+ */
+
+       .text
+       .code16
+ENTRY(boot_start)
+       jmp     boot_start_1
+       .balign 4
+ENTRY(boot_magic)
+       .long   X86_BOOT_MAGIC_2        /* checked for by bootxx code */
+ENTRY(boot_params)
+       .long   boot_start_1 - boot_params
+#include <boot_params.S>
+       . = boot_start + 0x80           /* space for patchable variables */
+boot_start_1:
+
+#if 0
+       /* Allow for boot_start not being %cs:0 */
+       call    2f
+2:     pop     %cx
+       sub     $2b, %cx                /* %ax is offset */
+       test    $0xf, %cx               /* check code seg aligned */
+       jz      3f
+       lret                            /* not playing if not */
+3:     mov     %cs, %ax
+       shr     $4, %cx
+       add     %cx, %ax                /* segment staring at boot_start */
+       push    %ax
+       push    $4f
+       lret
+4:
+#endif
+
+       mov     %cs, %ax
+       mov     %ax, %es
+
+       movl    %ecx, %ebp              /* move LBA out of the way */
+
+       /* Grab boot_params patched into bootxx by installboot */
+       cmpl    $X86_BOOT_MAGIC_1,-4(%si)       /* sanity check ptr */
+       jne     2f
+       mov     $boot_params, %di
+       movl    (%si),%ecx
+       cmp     $boot_start_1 - boot_params, %cx
+       jbe     1f
+       mov     $boot_start_1 - boot_params, %cx
+1:     cld
+       rep
+       movsb
+2:
+
+       mov     %ax, %ds
+       movl    $_end, %eax             /* top of bss */
+       shr     $4, %eax                /* as a segment */
+       add     $0x1001, %ax            /* and + 64k */
+       mov     %ax, %ss                /* for stack */
+       mov     $0xfffc, %sp            /* %sp at top of it */
+
+       call    gdt_fixup
+
+       calll   real_to_prot
+       .code32
+
+       movl    $_end, %ecx             /* zero bss */
+       movl    $__bss_start, %edi
+       subl    %edi, %ecx
+       shr     $2, %ecx                /* _end and __bss_start are aligned */
+       xor     %eax, %eax
+       rep
+       stosl
+
+       testb   $X86_BP_FLAGS_LBA64VALID, boot_params+4
+       jnz     1f
+       xorl    %ebp, %ebp              /* high part of LBA is not valid */
+1:
+
+       movzbl  %dl, %edx
+       push    %ebp                    /* high 32 bits of first sector */
+       push    %ebx                    /* first sector of bios partition */
+       push    %edx                    /* bios disk */
+       call    _C_LABEL(boot2)         /* C bootstrap code */
+       addl    $12, %esp
+       call    prot_to_real
+       .code16
+
+boot_fail:
+       push    %ax
+       movw    $1f, %si
+       call    message
+       pop     %si
+       call    message
+       jmp     loopstop
+1:     .asciz  "Boot2 failed: "
+
+ENTRY(_rtt)
+       .code32
+       call    prot_to_real
+       .code16
+loopstop:
+       movb    $0x86, %ah              /* delay for about a second */
+       movw    $16, %cx
+       int     $0x15
+       int     $0x18                   /* might be a boot fail entry */
+1:     sti
+       hlt
+       jmp     1b
diff --git a/sys/arch/i386/stand/boot/biosboot/Makefile b/sys/arch/i386/stand/boot/biosboot/Makefile
new file mode 100644 (file)
index 0000000..96780c1
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $
+
+PROG=  boot
+
+.include <../Makefile.boot>
diff --git a/sys/arch/i386/stand/boot/boot2.c b/sys/arch/i386/stand/boot/boot2.c
new file mode 100644 (file)
index 0000000..6356bcb
--- /dev/null
@@ -0,0 +1,522 @@
+/*     $NetBSD: boot2.c,v 1.57 2011/12/25 06:09:09 tsutsui Exp $       */
+
+/*-
+ * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2003
+ *     David Laight.  All rights reserved
+ * Copyright (c) 1996, 1997, 1999
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996, 1997
+ *     Perry E. Metzger.  All rights reserved.
+ * Copyright (c) 1997
+ *     Jason R. Thorpe.  All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Matthias Drochner.
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Based on stand/biosboot/main.c */
+
+#include <sys/types.h>
+#include <sys/reboot.h>
+#include <sys/bootblock.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <bootmod.h>
+#include <bootmenu.h>
+#include <vbe.h>
+#include "devopen.h"
+
+#ifdef SUPPORT_PS2
+#include <biosmca.h>
+#endif
+
+extern struct x86_boot_params boot_params;
+
+extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
+
+int errno;
+
+int boot_biosdev;
+daddr_t boot_biossector;
+
+static const char * const names[][2] = {
+       { "netbsd", "netbsd.gz" },
+       { "onetbsd", "onetbsd.gz" },
+       { "netbsd.old", "netbsd.old.gz" },
+};
+
+#define NUMNAMES (sizeof(names)/sizeof(names[0]))
+#define DEFFILENAME names[0][0]
+
+#define MAXDEVNAME 16
+
+static char *default_devname;
+static int default_unit, default_partition;
+static const char *default_filename;
+
+char *sprint_bootsel(const char *);
+void bootit(const char *, int, int);
+void print_banner(void);
+void boot2(int, uint64_t);
+
+void   command_help(char *);
+void   command_ls(char *);
+void   command_quit(char *);
+void   command_boot(char *);
+void   command_dev(char *);
+void   command_consdev(char *);
+void   command_modules(char *);
+void   command_multiboot(char *);
+
+const struct bootblk_command commands[] = {
+       { "help",       command_help },
+       { "?",          command_help },
+       { "ls",         command_ls },
+       { "quit",       command_quit },
+       { "boot",       command_boot },
+       { "dev",        command_dev },
+       { "consdev",    command_consdev },
+       { "modules",    command_modules },
+       { "load",       module_add },
+       { "multiboot",  command_multiboot },
+       { "vesa",       command_vesa },
+       { "splash",     splash_add },
+       { "rndseed",    rnd_add },
+       { "userconf",   userconf_add },
+       { NULL,         NULL },
+};
+
+int
+parsebootfile(const char *fname, char **fsname, char **devname,
+             int *unit, int *partition, const char **file)
+{
+       const char *col;
+
+       *fsname = "ufs";
+       *devname = default_devname;
+       *unit = default_unit;
+       *partition = default_partition;
+       *file = default_filename;
+
+       if (fname == NULL)
+               return 0;
+
+       if ((col = strchr(fname, ':')) != NULL) {       /* device given */
+               static char savedevname[MAXDEVNAME+1];
+               int devlen;
+               int u = 0, p = 0;
+               int i = 0;
+
+               devlen = col - fname;
+               if (devlen > MAXDEVNAME)
+                       return EINVAL;
+
+#define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
+               if (!isvalidname(fname[i]))
+                       return EINVAL;
+               do {
+                       savedevname[i] = fname[i];
+                       i++;
+               } while (isvalidname(fname[i]));
+               savedevname[i] = '\0';
+
+#define isnum(c) ((c) >= '0' && (c) <= '9')
+               if (i < devlen) {
+                       if (!isnum(fname[i]))
+                               return EUNIT;
+                       do {
+                               u *= 10;
+                               u += fname[i++] - '0';
+                       } while (isnum(fname[i]));
+               }
+
+#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
+               if (i < devlen) {
+                       if (!isvalidpart(fname[i]))
+                               return EPART;
+                       p = fname[i++] - 'a';
+               }
+
+               if (i != devlen)
+                       return ENXIO;
+
+               *devname = savedevname;
+               *unit = u;
+               *partition = p;
+               fname = col + 1;
+       }
+
+       if (*fname)
+               *file = fname;
+
+       return 0;
+}
+
+char *
+sprint_bootsel(const char *filename)
+{
+       char *fsname, *devname;
+       int unit, partition;
+       const char *file;
+       static char buf[80];
+
+       if (parsebootfile(filename, &fsname, &devname, &unit,
+                         &partition, &file) == 0) {
+               sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
+               return buf;
+       }
+       return "(invalid)";
+}
+
+static void
+clearit(void)
+{
+
+       if (bootconf.clear)
+               clear_pc_screen();
+}
+
+void
+bootit(const char *filename, int howto, int tell)
+{
+
+       if (tell) {
+               printf("booting %s", sprint_bootsel(filename));
+               if (howto)
+                       printf(" (howto 0x%x)", howto);
+               printf("\n");
+       }
+
+       if (exec_netbsd(filename, 0, howto, boot_biosdev < 0x80, clearit) < 0)
+               printf("boot: %s: %s\n", sprint_bootsel(filename),
+                      strerror(errno));
+       else
+               printf("boot returned\n");
+}
+
+void
+print_banner(void)
+{
+
+       clearit();
+#ifndef SMALL
+       int n;
+       if (bootconf.banner[0]) {
+               for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++) 
+                       printf("%s\n", bootconf.banner[n]);
+       } else {
+#endif /* !SMALL */
+               printf("\n"
+                      ">> %s, Revision %s (from NetBSD %s)\n"
+                      ">> Memory: %d/%d k\n",
+                      bootprog_name, bootprog_rev, bootprog_kernrev,
+                      getbasemem(), getextmem());
+
+#ifndef SMALL
+       }
+#endif /* !SMALL */
+}
+
+/*
+ * Called from the initial entry point boot_start in biosboot.S
+ *
+ * biosdev: BIOS drive number the system booted from
+ * biossector: Sector number of the NetBSD partition
+ */
+void
+boot2(int biosdev, uint64_t biossector)
+{
+       extern char twiddle_toggle;
+       int currname;
+       char c;
+
+       twiddle_toggle = 1;     /* no twiddling until we're ready */
+
+       initio(boot_params.bp_consdev);
+
+#ifdef SUPPORT_PS2
+       biosmca();
+#endif
+       gateA20();
+
+       boot_modules_enabled = !(boot_params.bp_flags
+                                & X86_BP_FLAGS_NOMODULES);
+       if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
+               biosvideomode();
+
+       vbe_init();
+
+       /* need to remember these */
+       boot_biosdev = biosdev;
+       boot_biossector = biossector;
+
+       /* try to set default device to what BIOS tells us */
+       bios2dev(biosdev, biossector, &default_devname, &default_unit,
+                &default_partition);
+
+       /* if the user types "boot" without filename */
+       default_filename = DEFFILENAME;
+
+#ifndef SMALL
+       if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
+               parsebootconf(BOOTCONF);
+       } else {
+               bootconf.timeout = boot_params.bp_timeout;
+       }
+       
+
+       /*
+        * If console set in boot.cfg, switch to it.
+        * This will print the banner, so we don't need to explicitly do it
+        */
+       if (bootconf.consdev)
+               command_consdev(bootconf.consdev);
+       else 
+               print_banner();
+
+       /* Display the menu, if applicable */
+       twiddle_toggle = 0;
+       if (bootconf.nummenu > 0) {
+               /* Does not return */
+               doboottypemenu();
+       }
+
+#else
+       twiddle_toggle = 0;
+       print_banner();
+#endif
+
+       printf("Press return to boot now, any other key for boot menu\n");
+       for (currname = 0; currname < NUMNAMES; currname++) {
+               printf("booting %s - starting in ",
+                      sprint_bootsel(names[currname][0]));
+
+#ifdef SMALL
+               c = awaitkey(boot_params.bp_timeout, 1);
+#else
+               c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
+#endif
+               if ((c != '\r') && (c != '\n') && (c != '\0')) {
+                   if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
+                       /* do NOT ask for password */
+                       bootmenu(); /* does not return */
+                   } else {
+                       /* DO ask for password */
+                       if (check_password((char *)boot_params.bp_password)) {
+                           /* password ok */
+                           printf("type \"?\" or \"help\" for help.\n");
+                           bootmenu(); /* does not return */
+                       } else {
+                           /* bad password */
+                           printf("Wrong password.\n");
+                           currname = 0;
+                           continue;
+                       }
+                   }
+               }
+
+               /*
+                * try pairs of names[] entries, foo and foo.gz
+                */
+               /* don't print "booting..." again */
+               bootit(names[currname][0], 0, 0);
+               /* since it failed, try compressed bootfile. */
+               bootit(names[currname][1], 0, 1);
+       }
+
+       bootmenu();     /* does not return */
+}
+
+/* ARGSUSED */
+void
+command_help(char *arg)
+{
+
+       printf("commands are:\n"
+              "boot [xdNx:][filename] [-12acdqsvxz]\n"
+              "     (ex. \"hd0a:netbsd.old -s\"\n"
+              "ls [path]\n"
+              "dev xd[N[x]]:\n"
+              "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
+              "vesa {modenum|on|off|enabled|disabled|list}\n"
+              "modules {on|off|enabled|disabled}\n"
+              "load {path_to_module}\n"
+              "multiboot [xdNx:][filename] [<args>]\n"
+              "userconf {command}\n"
+              "rndseed {path_to_rndseed_file}\n"
+              "help|?\n"
+              "quit\n");
+}
+
+void
+command_ls(char *arg)
+{
+       const char *save = default_filename;
+
+       default_filename = "/";
+       ls(arg);
+       default_filename = save;
+}
+
+/* ARGSUSED */
+void
+command_quit(char *arg)
+{
+
+       printf("Exiting...\n");
+       delay(1000000);
+       reboot();
+       /* Note: we shouldn't get to this point! */
+       panic("Could not reboot!");
+}
+
+void
+command_boot(char *arg)
+{
+       char *filename;
+       int howto;
+
+       if (parseboot(arg, &filename, &howto))
+               bootit(filename, howto, (howto & AB_VERBOSE) != 0);
+}
+
+void
+command_dev(char *arg)
+{
+       static char savedevname[MAXDEVNAME + 1];
+       char *fsname, *devname;
+       const char *file; /* dummy */
+
+       if (*arg == '\0') {
+               biosdisk_probe();
+               printf("default %s%d%c\n", default_devname, default_unit,
+                      'a' + default_partition);
+               return;
+       }
+
+       if (strchr(arg, ':') == NULL ||
+           parsebootfile(arg, &fsname, &devname, &default_unit,
+                         &default_partition, &file)) {
+               command_help(NULL);
+               return;
+       }
+
+       /* put to own static storage */
+       strncpy(savedevname, devname, MAXDEVNAME + 1);
+       default_devname = savedevname;
+}
+
+static const struct cons_devs {
+       const char      *name;
+       u_int           tag;
+} cons_devs[] = {
+       { "pc",         CONSDEV_PC },
+       { "com0",       CONSDEV_COM0 },
+       { "com1",       CONSDEV_COM1 },
+       { "com2",       CONSDEV_COM2 },
+       { "com3",       CONSDEV_COM3 },
+       { "com0kbd",    CONSDEV_COM0KBD },
+       { "com1kbd",    CONSDEV_COM1KBD },
+       { "com2kbd",    CONSDEV_COM2KBD },
+       { "com3kbd",    CONSDEV_COM3KBD },
+       { "auto",       CONSDEV_AUTO },
+       { NULL,         0 }
+};
+
+void
+command_consdev(char *arg)
+{
+       const struct cons_devs *cdp;
+
+       for (cdp = cons_devs; cdp->name; cdp++) {
+               if (strcmp(arg, cdp->name) == 0) {
+                       initio(cdp->tag);
+                       print_banner();
+                       return;
+               }
+       }
+       printf("invalid console device.\n");
+}
+
+void
+command_modules(char *arg)
+{
+
+       if (strcmp(arg, "enabled") == 0 ||
+           strcmp(arg, "on") == 0)
+               boot_modules_enabled = true;
+       else if (strcmp(arg, "disabled") == 0 ||
+           strcmp(arg, "off") == 0)
+               boot_modules_enabled = false;
+       else
+               printf("invalid flag, must be 'enabled' or 'disabled'.\n");
+}
+
+void
+command_multiboot(char *arg)
+{
+       char *filename;
+
+       filename = arg;
+       if (exec_multiboot(filename, gettrailer(arg)) < 0)
+               printf("multiboot: %s: %s\n", sprint_bootsel(filename),
+                      strerror(errno));
+       else
+               printf("boot returned\n");
+}
+
diff --git a/sys/arch/i386/stand/boot/conf.c b/sys/arch/i386/stand/boot/conf.c
new file mode 100644 (file)
index 0000000..fa45ac2
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $NetBSD: conf.c,v 1.5 2008/04/05 18:21:34 tsutsui Exp $  */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libsa/lfs.h>
+#ifdef SUPPORT_EXT2FS
+#include <lib/libsa/ext2fs.h>
+#endif
+#ifdef SUPPORT_MINIXFS3
+#include <lib/libsa/minixfs3.h>
+#endif
+#ifdef SUPPORT_USTARFS
+#include <lib/libsa/ustarfs.h>
+#endif
+#ifdef SUPPORT_DOSFS
+#include <lib/libsa/dosfs.h>
+#endif
+#ifdef SUPPORT_CD9660
+#include <lib/libsa/cd9660.h>
+#endif
+
+#include <biosdisk.h>
+
+struct devsw devsw[] = {
+       {"disk", biosdisk_strategy, biosdisk_open, biosdisk_close,
+        biosdisk_ioctl},
+};
+int ndevs = sizeof(devsw) / sizeof(struct devsw);
+
+struct fs_ops file_system[] = {
+#ifdef SUPPORT_CD9660
+       FS_OPS(cd9660),
+#endif
+#ifdef SUPPORT_USTARFS
+       FS_OPS(ustarfs),
+#endif
+       FS_OPS(ffsv1), FS_OPS(ffsv2),
+       FS_OPS(lfsv1), FS_OPS(lfsv2),
+#ifdef SUPPORT_EXT2FS
+       FS_OPS(ext2fs),
+#endif
+#ifdef SUPPORT_MINIXFS3
+       FS_OPS(minixfs3),
+#endif
+#ifdef SUPPORT_DOSFS
+       FS_OPS(dosfs),
+#endif
+};
+int nfsys = sizeof(file_system) / sizeof(struct fs_ops);
diff --git a/sys/arch/i386/stand/boot/devopen.c b/sys/arch/i386/stand/boot/devopen.c
new file mode 100644 (file)
index 0000000..7d504d3
--- /dev/null
@@ -0,0 +1,146 @@
+/*     $NetBSD: devopen.c,v 1.8 2010/12/24 20:40:42 jakllsch Exp $      */
+
+/*-
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bang Jun-Young.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996, 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <sys/types.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <biosdisk.h>
+#include "devopen.h"
+#ifdef _STANDALONE
+#include <bootinfo.h>
+#endif
+#ifdef SUPPORT_PS2
+#include <biosmca.h>
+#endif
+
+static int dev2bios(char *, int, int *);
+
+static int
+dev2bios(char *devname, int unit, int *biosdev)
+{
+
+       if (strcmp(devname, "hd") == 0)
+               *biosdev = 0x80 + unit;
+       else if (strcmp(devname, "fd") == 0)
+               *biosdev = 0x00 + unit;
+       else if (strcmp(devname, "cd") == 0)
+               *biosdev = boot_biosdev;
+       else
+               return ENXIO;
+
+       return 0;
+}
+
+void
+bios2dev(int biosdev, daddr_t sector, char **devname, int *unit, int *partition)
+{
+
+       /* set default */
+       *unit = biosdev & 0x7f;
+
+       if (biosdev & 0x80) {
+               /*
+                * There seems to be no standard way of numbering BIOS
+                * CD-ROM drives. The following method is a little tricky
+                * but works nicely.
+                */
+               if (biosdev >= 0x80 + get_harddrives()) {
+                       *devname = "cd";
+                       *unit = 0;              /* override default */
+               } else
+                       *devname = "hd";
+       } else
+               *devname = "fd";
+
+       *partition = biosdisk_findpartition(biosdev, sector);
+}
+
+#ifdef _STANDALONE
+struct btinfo_bootpath bibp;
+extern bool kernel_loaded;
+#endif
+
+/*
+ * Open the BIOS disk device
+ */
+int
+devopen(struct open_file *f, const char *fname, char **file)
+{
+       char *fsname, *devname;
+       int unit, partition;
+       int biosdev;
+       int error;
+
+       if ((error = parsebootfile(fname, &fsname, &devname,
+                                  &unit, &partition, (const char **) file))
+           || (error = dev2bios(devname, unit, &biosdev)))
+               return error;
+
+       f->f_dev = &devsw[0];           /* must be biosdisk */
+
+#ifdef _STANDALONE
+       if (!kernel_loaded) {
+               strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
+               BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
+       }
+#endif
+
+       return biosdisk_open(f, biosdev, partition);
+}
diff --git a/sys/arch/i386/stand/boot/devopen.h b/sys/arch/i386/stand/boot/devopen.h
new file mode 100644 (file)
index 0000000..2291914
--- /dev/null
@@ -0,0 +1,5 @@
+/*     $NetBSD: devopen.h,v 1.4 2010/12/24 20:40:42 jakllsch Exp $     */
+
+extern int boot_biosdev;
+
+void bios2dev(int, daddr_t, char **, int *, int *);
diff --git a/sys/arch/i386/stand/boot/version b/sys/arch/i386/stand/boot/version
new file mode 100644 (file)
index 0000000..600e3dc
--- /dev/null
@@ -0,0 +1,49 @@
+$NetBSD: version,v 1.15 2011/02/09 04:37:54 jmcneill Exp $
+
+NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE.  The format of this
+file is important - make sure the entries are appended on end, last item
+is taken as the current.
+
+2.0:   Change over to Matthias Drochner's two-stage boot system.
+       All code is completely new.
+2.1:   New welcoming banner.
+2.2:   Use common menu / parsing functions with other bootloaders.
+       New framework to pass information to the kernel.
+2.3:   Switch to new NetBSD MBR partition ID.
+2.4:   Support BIOS Int13-Extensions.
+2.5:   Support ustarfs boot.
+2.6:   Support ELF boot.
+2.7:   Support on-the-fly switching of console devices.
+2.8:   Support verbose/quiet boot.
+2.9:   Recognize PS/2 L40 at runtime and use appropriate gate A20
+       initialization (rather than using a compile flag).
+       Recognize ESDI disks and identify them as ed(4) for COMPAT_OLDBOOT.
+2.10:  g/c COMPAT_OLDBOOT.
+2.11:  loadfile() update:  ELF symbols no longer need backward seeks.
+2.12:  loadfile() update to avoid backwards seeks for ELF Program Headers.
+2.13:  Support boot from 1.44MB floppies in 2.88MB floppy drives.
+2.14:  Add a quirk for BIOSes which report extended memory size
+       in slightly nonstandard way in int15, function 0xE801.
+2.15:  Use int15/0xc7 to get memory information on machines which support
+       it, like later IBM PS/2 machines.
+2.16:  Move 16bit %ss to allow >64k for code, data and stack.
+       Default partition to that passed in by mbr code.
+       Support limited filename globbing in 'ls' command.
+       Use .code16 and .code32 directives
+3.0:   Separate out into bootxx and boot
+3.1:   Rename to /usr/mdec/boot.
+       Leave space in bootxx for FAT32 BPB and MBR partition table.
+       Keep MBR's existing BPB and partition table when installing bootxx.
+3.2:   Add support for passing boot wedge information to the kernel.
+3.3:   Add support for cd9660 file system.
+5.0:   Support for boot menu, modules.
+5.1:   Change boot messages to replace build date with kernel version.
+5.2:   Support for multiboot.
+5.3:   Autoload kernel module for root file system.
+5.4:   The VESA VBE mode number is now passed to the kernel so it can be
+       restored on ACPI resume.
+5.5:   Adjust stack and heap areas to not overlap.
+5.6:   GUID Partition Table support.
+5.7:   Recognize 64-bit LBA from bootxx.
+5.8:   Support for splash images.
+5.9:   VESA VBE/DDC EDID support.
diff --git a/sys/arch/i386/stand/bootxx/Makefile b/sys/arch/i386/stand/bootxx/Makefile
new file mode 100644 (file)
index 0000000..05a3da2
--- /dev/null
@@ -0,0 +1,21 @@
+# $NetBSD: Makefile,v 1.14 2010/12/29 17:44:03 jakllsch Exp $
+
+SUBDIR=        bootxx_ffsv1 .WAIT bootxx_ffsv2 bootxx_lfsv1 bootxx_lfsv2
+SUBDIR+=bootxx_msdos bootxx_ustarfs
+
+# Ext2fs doesn't have enough free space (it has only 1KB)
+# to store this primary bootloader, but we can put it into
+# an independent small 'boot' partition as NetBSD/hp300 does.
+SUBDIR+=bootxx_ext2fs
+SUBDIR+=bootxx_minixfs3
+
+LIBOBJ= ${.OBJDIR}
+.MAKEOVERRIDES+= LIBOBJ
+
+.include <bsd.subdir.mk>
+.include <bsd.obj.mk>
+
+cleandir distclean: .WAIT cleanlibdir
+
+cleanlibdir:
+       -rm -rf lib
diff --git a/sys/arch/i386/stand/bootxx/Makefile.bootxx b/sys/arch/i386/stand/bootxx/Makefile.bootxx
new file mode 100644 (file)
index 0000000..ab80745
--- /dev/null
@@ -0,0 +1,154 @@
+# $NetBSD: Makefile.bootxx,v 1.42 2011/06/20 06:52:38 mrg Exp $
+
+S=     ${.CURDIR}/../../../../..
+
+AFLAGS.bootxx.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.label.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.pbr.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+
+PIE_CFLAGS=
+PIE_LDFLAGS=
+PIE_AFLAGS=
+NOMAN=
+PROG?= bootxx_${FS}
+BINDIR= /usr/mdec
+BINMODE= 0444
+
+PRIMARY_LOAD_ADDRESS=0x1000
+SECONDARY_LOAD_ADDRESS=0x10000
+
+# We ought (need?) to fit into track 0 of a 1.2M floppy.
+# This restricts us to 15 sectors (including pbr and label)
+BOOTXX_SECTORS?=15
+BOOTXX_MAXSIZE?= $$(( ${BOOTXX_SECTORS} * 512 ))
+
+SRCS= pbr.S label.S bootxx.S boot1.c
+
+.include <bsd.own.mk>
+
+STRIPFLAG=     # nothing
+
+LIBCRT0=       # nothing
+LIBCRTBEGIN=   # nothing
+LIBCRTEND=     # nothing
+LIBC=          # nothing
+
+BINDIR=/usr/mdec
+BINMODE=444
+
+.PATH: ${.CURDIR}/.. ${.CURDIR}/../../lib
+
+LDFLAGS+= -nostdlib -Wl,-N -Wl,-e,start
+CPPFLAGS+= -DBOOTXX
+# CPPFLAGS+= -D__daddr_t=int32_t
+CPPFLAGS+= -I ${.CURDIR}/../../lib -I ${.OBJDIR}
+CPPFLAGS+= -DBOOTXX_SECTORS=${BOOTXX_SECTORS}
+CPPFLAGS+= -DPRIMARY_LOAD_ADDRESS=${PRIMARY_LOAD_ADDRESS}
+CPPFLAGS+= -DSECONDARY_LOAD_ADDRESS=${SECONDARY_LOAD_ADDRESS}
+CPPFLAGS+= -DXXfs_open=${FS}_open
+CPPFLAGS+= -DXXfs_close=${FS}_close
+CPPFLAGS+= -DXXfs_read=${FS}_read
+CPPFLAGS+= -DXXfs_stat=${FS}_stat
+CPPFLAGS+= -DFS=${FS}
+# CPPFLAGS+= -DBOOT_MSG_COM0
+
+# Make sure we override any optimization options specified by the user
+.include "${.PARSEDIR}/../Makefile.inc"
+COPTS= ${OPT_SIZE.${ACTIVE_CC}}
+DBG=
+
+CPPFLAGS+= -DNO_LBA_CHECK
+
+.if defined(HAVE_GCC)
+.if ${MACHINE_ARCH} == "x86_64"
+LDFLAGS+=  -Wl,-m,elf_i386
+AFLAGS+=   -m32
+CPUFLAGS=  -m32
+LIBKERN_ARCH=i386
+KERNMISCMAKEFLAGS="LIBKERN_ARCH=i386"
+.else
+CPPFLAGS+= -DEPIA_HACK
+CPUFLAGS=  -march=i386 -mtune=i386
+.endif
+.endif
+
+CFLAGS+= -Wall -Wmissing-prototypes -Wstrict-prototypes
+CPPFLAGS+= -nostdinc -D_STANDALONE
+CPPFLAGS+= -I$S
+
+CPPFLAGS+= -DLIBSA_SINGLE_FILESYSTEM=xxfs \
+               -DLIBSA_NO_TWIDDLE \
+               -DLIBSA_NO_FD_CHECKING \
+               -DLIBSA_NO_RAW_ACCESS \
+               -DLIBSA_NO_FS_WRITE \
+               -DLIBSA_NO_FS_SEEK \
+               -DLIBSA_SINGLE_DEVICE=blkdev \
+               -DLIBKERN_OPTIMISE_SPACE \
+               -D"blkdevioctl(x,y,z)=EINVAL" \
+               -D"blkdevclose(f)=0" \
+               -D"devopen(f,n,fl)=(*(fl)=(void *)n,0)" \
+               -DLIBSA_NO_DISKLABEL_MSGS
+
+# -DLIBSA_FS_SINGLECOMPONENT 
+
+# CPPFLAGS+= -DBOOTXX_RAID1_SUPPORT
+
+I386_STAND_DIR?= $S/arch/i386/stand
+
+CLEANFILES+= machine x86
+
+.if !make(obj) && !make(clean) && !make(cleandir)
+.BEGIN:
+       -rm -f machine && ln -s $S/arch/i386/include machine
+       -rm -f x86 && ln -s $S/arch/x86/include x86
+.ifdef LIBOBJ
+       -rm -f lib && ln -s ${LIBOBJ}/lib lib
+       mkdir -p ${LIBOBJ}/lib
+.endif
+.endif
+
+### find out what to use for libi386
+I386DIR= ${I386_STAND_DIR}/lib
+.include "${I386DIR}/Makefile.inc"
+LIBI386= ${I386LIB}
+
+### find out what to use for libsa
+SA_AS= library
+SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+.include "${S}/lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+### find out what to use for libkern
+KERN_AS=        library
+.include "${S}/lib/libkern/Makefile.inc"
+LIBKERN=        ${KERNLIB}
+
+
+cleandir distclean: .WAIT cleanlibdir
+
+cleanlibdir:
+       -rm -rf lib
+
+LIBLIST= ${LIBI386} ${LIBSA} ${LIBKERN} ${LIBI386} ${LIBSA}
+
+CLEANFILES+= ${PROG}.sym ${PROG}.map
+
+${PROG}: ${OBJS} ${LIBLIST}
+       ${_MKTARGET_LINK}
+       ${CC} -o ${PROG}.sym ${LDFLAGS} -Wl,-Ttext,${PRIMARY_LOAD_ADDRESS} \
+               -Wl,-Map,${PROG}.map -Wl,-cref ${OBJS} ${LIBLIST}
+       ${OBJCOPY} -O binary ${PROG}.sym ${PROG}
+       @ sz=$$(${TOOL_STAT} -f '%z' ${PROG}); \
+       if [ "$$sz" -gt "${BOOTXX_MAXSIZE}" ]; then \
+               echo "### ${PROG} size $$sz is larger than ${BOOTXX_MAXSIZE}" >&2; \
+               rm ${PROG}; \
+               ! :; \
+       else \
+               : pad to sector boundary; \
+               pad=$$(( 512 - ( $$sz & 511 ) )); \
+               [ $$pad = 512 ] || \
+                   dd if=/dev/zero bs=1 count=$$pad >>${PROG} 2>/dev/null; \
+               echo "${PROG} size $$sz, $$((${BOOTXX_MAXSIZE} - $$sz)) free"; \
+       fi
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/i386/stand/bootxx/boot1.c b/sys/arch/i386/stand/bootxx/boot1.c
new file mode 100644 (file)
index 0000000..9ecbb47
--- /dev/null
@@ -0,0 +1,158 @@
+/*     $NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $      */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $");
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#include <biosdisk_ll.h>
+
+#include <sys/param.h>
+#include <sys/bootblock.h>
+#include <sys/disklabel.h>
+#include <dev/raidframe/raidframevar.h>        /* For RF_PROTECTED_SECTORS */
+
+#define XSTR(x) #x
+#define STR(x) XSTR(x)
+
+static daddr_t bios_sector;
+
+static struct biosdisk_ll d;
+
+const char *boot1(uint32_t, uint64_t *);
+extern void putstr(const char *);
+
+extern struct disklabel ptn_disklabel;
+
+static int
+ob(void)
+{
+       return open("boot", 0);
+}
+
+const char *
+boot1(uint32_t biosdev, uint64_t *sector)
+{
+       struct stat sb;
+       int fd;
+
+       bios_sector = *sector;
+       d.dev = biosdev;
+
+       putstr("\r\nNetBSD/x86 " STR(FS) " Primary Bootstrap\r\n");
+
+       if (set_geometry(&d, NULL))
+               return "set_geometry\r\n";
+
+       /*
+        * We default to the filesystem at the start of the
+        * MBR partition
+        */
+       fd = ob();
+       if (fd != -1)
+               goto done;
+       /*
+        * Maybe the filesystem is enclosed in a raid set.
+        * add in size of raidframe header and try again.
+        * (Maybe this should only be done if the filesystem
+        * magic number is absent.)
+        */
+       bios_sector += RF_PROTECTED_SECTORS;
+       fd = ob();
+       if (fd != -1)
+               goto done;
+
+#ifdef BOOT_FROM_MINIXFS3
+       bios_sector -= RF_PROTECTED_SECTORS;
+       bios_sector += 32; /* XXX put somewhere as constant */
+       *sector = bios_sector;
+
+       fd = ob();
+       if (fd != -1)
+               goto done;
+#endif
+
+       /*
+        * Nothing at the start of the MBR partition, fallback on
+        * partition 'a' from the disklabel in this MBR partition.
+        */
+       if (ptn_disklabel.d_magic != DISKMAGIC ||
+           ptn_disklabel.d_magic2 != DISKMAGIC ||
+           ptn_disklabel.d_partitions[0].p_fstype == FS_UNUSED)
+               goto done;
+       bios_sector = ptn_disklabel.d_partitions[0].p_offset;
+       *sector = bios_sector;
+       if (ptn_disklabel.d_partitions[0].p_fstype == FS_RAID)
+               bios_sector += RF_PROTECTED_SECTORS;
+
+       fd = ob();
+
+done:
+       /* if we fail here, so will fstat, so keep going */
+       if (fd == -1 || fstat(fd, &sb) == -1)
+               return "Can't open /boot\r\n";
+
+       biosdev = (uint32_t)sb.st_size;
+#if 0
+       if (biosdev > SECONDARY_MAX_LOAD)
+               return "/boot too large\r\n";
+#endif
+
+       if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, biosdev) != biosdev)
+               return "/boot load failed\r\n";
+
+       if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2)
+               return "Invalid /boot file format\r\n";
+
+       /* We need to jump to the secondary bootstrap in realmode */
+       return 0;
+}
+
+int
+blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize)
+{
+       if (flag != F_READ)
+               return EROFS;
+
+       if (size & (BIOSDISK_DEFAULT_SECSIZE - 1))
+               return EINVAL;
+
+       if (rsize)
+               *rsize = size;
+
+       if (size != 0 && readsects(&d, bios_sector + dblk,
+                                  size / BIOSDISK_DEFAULT_SECSIZE,
+                                  buf, 1) != 0)
+               return EIO;
+
+       return 0;
+}
diff --git a/sys/arch/i386/stand/bootxx/bootxx.S b/sys/arch/i386/stand/bootxx/bootxx.S
new file mode 100644 (file)
index 0000000..ead430c
--- /dev/null
@@ -0,0 +1,136 @@
+/*     $NetBSD: bootxx.S,v 1.10 2011/01/06 01:08:48 jakllsch Exp $     */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <sys/bootblock.h>
+
+/*
+ * Code linked to 0xa00 and copied to sectors 2+ of the netbsd boot
+ * partition by MI /usr/sbin/installboot.
+ * Read into memory by code in pbr.S
+ *
+ * On entry:
+ *     %dl                     BIOS drive number
+ *     %edi:%esi               Sector number of NetBSD partition
+ *     %cs, %ds, %es, %ss      All zero
+ *     %sp                     near 0xfffc
+ */
+       .text
+       .code16
+ENTRY(bootxx)
+       jmp     1f
+       .balign 4
+ENTRY(bootxx_magic)
+       .long   X86_BOOT_MAGIC_1        /* checked by installboot & pbr code */
+boot_params:                           /* space for patchable variables */
+       .long   1f - boot_params        /* length of this data area */
+#include <boot_params.S>
+       . = bootxx + 0x80               /* Space for patching unknown params */
+
+1:     call    gdt_fixup
+
+       calll   real_to_prot
+       .code32
+
+       push    %edi
+       movl    $_end, %ecx             /* zero bss */
+       movl    $__bss_start, %edi
+       subl    %edi, %ecx
+       shr     $2, %ecx                /* _end and __bss_start are aligned */
+       xor     %eax, %eax
+       rep
+       stosl
+       pop     %edi
+
+       movzbl  %dl, %edx
+       push    %edi                    /* save args for secondary bootstrap */
+       push    %esi
+       movl    %esp, %esi              /* address of sector number */
+       push    %edx
+       push    %esi                    /* args for boot1 */
+       push    %edx
+       call    _C_LABEL(boot1)         /* C code to load /boot */
+       add     $8, %esp
+       call    prot_to_real
+       .code16
+
+       test    %ax, %ax
+       jnz     boot_fail
+
+       pop     %edx                    /* bios disk number */
+       pop     %ebx                    /* expected partition start sector */
+       pop     %ecx
+       movl    $boot_params, %esi
+       orb     $X86_BP_FLAGS_LBA64VALID, 4(%esi)
+       lcall   $SECONDARY_LOAD_ADDRESS/16, $0
+
+boot_fail:
+       push    %ax                     /* error string from boot1 */
+       movw    errno, %ax
+       aam                             /* largest errno is < 100 */
+       addw    $('0' << 8) | '0', %ax  /* to ascii */
+       rorw    $8, %ax
+       cmpb    $'0', %al               /* supress leading zero */
+       jne     10f
+       movb    $' ', %al
+10:    movw    %ax, 12f
+       movw    $11f, %si
+       call    message                 /* output boot failed message */
+       pop     %si
+       call    message                 /* and text from boot1 */
+       jmp     loopstop
+11:    .ascii  "Boot failed (errno "
+12:    .asciz  "xx): "
+
+ENTRY(_rtt)
+       .code32
+       call    prot_to_real
+       .code16
+loopstop:
+       movb    0x86, %ah               /* delay for about a second */
+       movw    $16, %cx
+       int     $0x15
+       int     $0x18                   /* might be a boot fail entry */
+1:     sti                             /* if not loopstop */
+       hlt
+       jmp     1b
+
+       /*
+        * Vector the fs calls through here so we can support multiple
+        * file system types with one copy of the library code and
+        * multiple copies of this file.
+        */
+       .global xxfs_open, xxfs_close, xxfs_read, xxfs_stat
+       .code32
+xxfs_open:     jmp     XXfs_open
+xxfs_close:    jmp     XXfs_close
+xxfs_read:     jmp     XXfs_read
+xxfs_stat:     jmp     XXfs_stat
diff --git a/sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile
new file mode 100644 (file)
index 0000000..6486276
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2010/09/11 13:06:37 tsutsui Exp $
+
+FS=ext2fs
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile
new file mode 100644 (file)
index 0000000..349cbfc
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=ffsv1
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile
new file mode 100644 (file)
index 0000000..f4d3816
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=ffsv2
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile b/sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile
new file mode 100644 (file)
index 0000000..b2a8ce3
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=lfsv1
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile b/sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile
new file mode 100644 (file)
index 0000000..55cec87
--- /dev/null
@@ -0,0 +1,5 @@
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
+
+FS=lfsv2
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile b/sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile
new file mode 100644 (file)
index 0000000..ba1e4e8
--- /dev/null
@@ -0,0 +1,7 @@
+#      $NetBSD$
+
+PROG=bootxx_minixfs3
+FS=minixfs3
+CPPFLAGS=-DBOOT_FROM_MINIXFS3 -DTERSE_ERROR
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile b/sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile
new file mode 100644 (file)
index 0000000..536590b
--- /dev/null
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $
+
+PROG=  bootxx_msdos
+FS=    dosfs
+CPPFLAGS=-DBOOT_FROM_FAT -DTERSE_ERROR
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile
new file mode 100644 (file)
index 0000000..5fde874
--- /dev/null
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile,v 1.3 2009/11/18 21:02:16 dsl Exp $
+
+FS=ustarfs
+
+BOOTXX_SECTORS=16
+
+.include <../Makefile.bootxx>
diff --git a/sys/arch/i386/stand/bootxx/label.S b/sys/arch/i386/stand/bootxx/label.S
new file mode 100644 (file)
index 0000000..dc4b986
--- /dev/null
@@ -0,0 +1,19 @@
+/*     $NetBSD: label.S,v 1.3 2005/12/11 12:17:48 christos Exp $       */
+
+#include <machine/asm.h>
+
+/*
+ * This fills in the space taken by the NetBSD disklabel in the first
+ * NetBSD partition on the disk.
+ * However it is possible that we are booting from a subsequent
+ * NetBSD partition, so must not access the disklabel in this space.
+ *
+ * Recent kernels (but not the disklabel program) write the label to
+ * all NetBSD MBR partitions (including extended ones).
+ * So we make it available to boot1().
+ */
+
+       .text
+       .global _C_LABEL(ptn_disklabel)
+_C_LABEL(ptn_disklabel):
+       .fill   512
diff --git a/sys/arch/i386/stand/bootxx/pbr.S b/sys/arch/i386/stand/bootxx/pbr.S
new file mode 100644 (file)
index 0000000..d93983b
--- /dev/null
@@ -0,0 +1,447 @@
+/*     $NetBSD: pbr.S,v 1.20 2011/08/17 00:07:38 jakllsch Exp $        */
+
+/*-
+ * Copyright (c) 2003,2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * i386 partition boot code
+ *
+ * This code resides in sector zero of the netbsd partition, or sector
+ * zero of an unpartitioned disk (eg a floppy).
+ * Sector 1 is assumed to contain the netbsd disklabel.
+ * Sectors 2 until the end of the track contain the next phase of bootstrap.
+ * Which know how to read the interactive 'boot' program from filestore.
+ * The job of this code is to read in the phase 1 bootstrap.
+ *
+ * Makefile supplies:
+ * PRIMARY_LOAD_ADDRESS:       Address we load code to (0x1000).
+ * BOOTXX_SECTORS:             Number of sectors we load (15).
+ * X86_BOOT_MAGIC_1:           A random magic number.
+ *
+ * Although this code is executing at 0x7c00, it is linked to address 0x1000.
+ * All data references MUST be fixed up using R().
+ */
+
+#include <machine/asm.h>
+#include <sys/bootblock.h>
+
+#define        OURADDR         0x7c00          /* our address */
+#define BOOTADDR       PRIMARY_LOAD_ADDRESS
+
+#define R(a) (a - BOOTADDR + OURADDR)
+
+#define lba_info R(_lba_info)
+#define lba_sector R(_lba_sector)
+#define errtxt R(_errtxt)
+#define errcod R(_errcod)
+#define newline R(_newline)
+
+#define TABENTRYSIZE   (MBR_BS_PARTNAMESIZE + 1)
+#define NAMETABSIZE    (4 * TABENTRYSIZE)
+
+#ifdef BOOT_FROM_FAT
+#define MBR_AFTERBPB   90              /* BPB size in FAT32 partition BR */
+#else
+#define MBR_AFTERBPB   62              /* BPB size in floppy master BR */
+#endif
+
+#ifdef TERSE_ERROR
+/*
+ * Error codes. Done this way to save space.
+ */
+#define ERR_READ       '2'             /* Read error */
+#define ERR_NO_BOOTXX  'B'             /* No bootxx_xfs in 3rd sector */
+#define        ERR_PTN         'P'             /* partition not defined */
+#define        ERR_NO_LBA      'L'             /* sector above chs limit */
+
+#define        set_err(err)    movb    $err, %al
+
+#else
+#define        set_err(err)    mov     $R(err), %ax
+#endif
+
+/*
+ * This code is loaded to addresss 0:7c00 by either the system BIOS
+ * (for a floppy) or the mbr boot code.  Since the boot program will
+ * be loaded to address 1000:0, we don't need to relocate ourselves
+ * and can load the subsequent blocks (that load boot) to an address
+ * of our choosing. 0:1000 is a not unreasonable choice.
+ *
+ * On entry the BIOS drive number is in %dl and %esi may contain the
+ * sector we were loaded from (if we were loaded by NetBSD mbr code).
+ * In any case we have to re-read sector zero of the disk and hunt
+ * through the BIOS partition table for the NetBSD partition.
+ *
+ * Or, we may have been loaded by a GPT hybrid MBR, handoff state is
+ * specified in T13 EDD-4 annex A.
+ */
+
+       .text
+       .code16
+ENTRY(start)
+       /*
+        * The PC BIOS architecture defines a Boot Parameter Block (BPB) here.
+        * The actual format varies between different MS-DOS versions, but
+        * apparently some system BIOS insist on patching this area
+        * (especially on LS120 drives - which I thought had an MBR...).
+        * The initial jmp and nop are part of the standard and may be
+        * tested for by the system BIOS.
+        */
+       jmp     start0
+       nop
+       .ascii  "NetBSD60"              /* oemname (8 bytes) */
+
+       . = start + MBR_BPB_OFFSET      /* move to start of BPB */
+                                       /* (ensures oemname doesn't overflow) */
+
+       . = start + MBR_AFTERBPB        /* skip BPB */
+start0:
+       xor     %cx, %cx                /* don't trust values of ds, es or ss */
+       mov     %cx, %ss
+       mov     %cx, %sp
+       mov     %cx, %es
+#ifndef BOOT_FROM_FAT
+       cmpl    $0x54504721, %eax       /* did a GPT hybrid MBR start us? */
+       je      boot_gpt
+#endif
+       mov     %cx, %ds
+       xor     %ax, %ax
+
+       /* A 'reset disk system' request is traditional here... */
+       push    %dx                     /* some BIOS zap %dl here :-( */
+       int     $0x13                   /* ah == 0 from code above */
+       pop     %dx
+
+       /* Read from start of disk */
+       incw    %cx                     /* track zero sector 1 */
+       movb    %ch, %dh                /* dh = head = 0 */
+       call    chs_read
+
+/* See if this is our code, if so we have already loaded the next stage */
+
+       xorl    %ebp, %ebp              /* pass sector 0 to next stage */
+       movl    (%bx), %eax             /* MBR code shouldn't even have ... */
+       cmpl    R(start), %eax          /* ... a jmp at the start. */
+       je      pbr_read_ok1
+
+/* Now scan the MBR partition table for a netbsd partition */
+       
+       xorl    %ebx, %ebx              /* for base extended ptn chain */
+scan_ptn_tbl:
+       xorl    %ecx, %ecx              /* for next extended ptn */
+       movw    $BOOTADDR + MBR_PART_OFFSET, %di
+1:     movb    4(%di), %al             /* mbrp_type */
+       movl    8(%di), %ebp            /* mbrp_start == LBA sector */
+       addl    lba_sector, %ebp        /* add base of extended partition */
+#ifdef BOOT_FROM_FAT
+       cmpb    $MBR_PTYPE_FAT12, %al
+       je      5f
+       cmpb    $MBR_PTYPE_FAT16S, %al
+       je      5f
+       cmpb    $MBR_PTYPE_FAT16B, %al
+       je      5f
+       cmpb    $MBR_PTYPE_FAT32, %al
+       je      5f
+       cmpb    $MBR_PTYPE_FAT32L, %al
+       je      5f
+       cmpb    $MBR_PTYPE_FAT16L, %al
+       je      5f
+#elif BOOT_FROM_MINIXFS3
+       cmpb    $MBR_PTYPE_MINIX_14B, %al
+       je      5f
+#else
+       cmpb    $MBR_PTYPE_NETBSD, %al
+#endif
+       jne     10f
+5:     testl   %esi, %esi              /* looking for a specific sector? */
+       je      boot
+       cmpl    %ebp, %esi              /* ptn we wanted? */
+       je      boot
+       /* check for extended partition */
+10:    cmpb    $MBR_PTYPE_EXT, %al
+       je      15f
+       cmpb    $MBR_PTYPE_EXT_LBA, %al
+       je      15f
+       cmpb    $MBR_PTYPE_EXT_LNX, %al
+       jne     20f
+15:    movl    8(%di), %ecx            /* sector of next ext. ptn */
+20:    add     $0x10, %di
+       cmp     $BOOTADDR + MBR_MAGIC_OFFSET, %di
+       jne     1b
+
+       /* not in base partitions, check extended ones */
+       jecxz   no_netbsd_ptn
+       testl   %ebx, %ebx
+       jne     30f
+       xchgl   %ebx, %ecx              /* save base of ext ptn chain */
+30:    addl    %ebx, %ecx              /* address this ptn */
+       movl    %ecx, lba_sector        /* sector to read */
+       call    read_lba
+       jmp     scan_ptn_tbl
+
+no_netbsd_ptn:
+       /* Specific sector not found: try again looking for first NetBSD ptn */
+       testl   %esi, %esi
+       set_err(ERR_PTN)
+       jz      error
+       xorl    %esi, %esi
+       movl    %esi, lba_sector
+       jmp     start
+
+/*
+ * Sector below CHS limit
+ * Do a cylinder-head-sector read instead
+ * I believe the BIOS should do reads that cross track boundaries.
+ * (but the read should start at the beginning of a track...)
+ */
+read_chs:
+       movb    1(%di), %dh                     /* head */
+       movw    2(%di), %cx                     /* ch=cyl, cl=sect */
+       call    chs_read
+pbr_read_ok1:
+       jmp     pbr_read_ok
+
+/*
+ * Active partition pointed to by di.
+ *
+ * We can either do a CHS (Cylinder Head Sector) or an LBA (Logical
+ * Block Address) read.  Always doing the LBA one
+ * would be nice - unfortunately not all systems support it.
+ * Also some may contain a separate (eg SCSI) BIOS that doesn't
+ * support it even when the main BIOS does.
+ *
+ * The safest thing seems to be to find out whether the sector we
+ * want is inside the CHS sector count.  If it is we use CHS, if
+ * outside we use LBA.
+ *
+ * Actually we check that the CHS values reference the LBA sector,
+ * if not we assume that the LBA sector is above the limit, or that
+ * the geometry used (by fdisk) isn't correct.
+ */
+boot:
+       movl    %ebp, lba_sector        /* to control block */
+       testl   %ebx, %ebx              /* was it an extended ptn? */
+       jnz     boot_lba                /* yes - boot with LBA reads */
+
+/* get CHS values from BIOS */
+       push    %dx                             /* save drive number */
+       movb    $8, %ah
+       int     $0x13                           /* chs info */
+
+/*
+ * Validate geometry, if the CHS sector number doesn't match the LBA one
+ * we'll do an LBA read.
+ * calc: (cylinder * number_of_heads + head) * number_of_sectors + sector
+ * and compare against LBA sector number.
+ * Take a slight 'flier' and assume we can just check 16bits (very likely
+ * to be true because the number of sectors per track is 63).
+ */
+       movw    2(%di), %ax                     /* cylinder + sector */
+       push    %ax                             /* save for sector */
+       shr     $6, %al
+       xchgb   %al, %ah                        /* 10 bit cylinder number */
+       shr     $8, %dx                         /* last head */
+       inc     %dx                             /* number of heads */
+       mul     %dx
+       mov     1(%di), %dl                     /* head we want */
+       add     %dx, %ax
+       and     $0x3f, %cx                      /* number of sectors */
+       mul     %cx
+       pop     %dx                             /* recover sector we want */
+       and     $0x3f, %dx
+       add     %dx, %ax
+       dec     %ax
+       pop     %dx                             /* recover drive nmber */
+
+       cmp     %bp, %ax
+       je      read_chs
+
+check_lba:
+#ifdef NO_LBA_CHECK
+       jmp     boot_lba
+#else
+/*
+ * Determine whether we have int13-extensions, by calling
+ * int 13, function 41. Check for the magic number returned,
+ * and the disk packet capability.
+ *
+ * This is actually relatively pointless:
+ * 1) we only use LBA reads if CHS ones would fail
+ * 2) the MBR code managed to read the same sectors
+ * 3) the BIOS will (ok should) reject the LBA read as a bad BIOS call
+ */
+       movw    $0x55aa, %bx
+       movb    $0x41, %ah
+       int     $0x13
+       jc      1f                              /* no int13 extensions */
+       cmpw    $0xaa55, %bx
+       jnz     1f
+       testb   $1, %cl
+       jnz     boot_lba
+1:     set_err(ERR_NO_LBA)
+#endif /* NO_LBA_CHECK */
+
+/*
+ * Something went wrong,
+ * Output error code,
+ */
+
+error:
+#ifdef TERSE_ERROR
+       movb    %al, errcod
+       movw    $errtxt, %si
+       call    message
+#else
+       push    %ax
+       movw    $errtxt, %si
+       call    message
+       pop     %si
+       call    message
+       movw    $newline, %si
+       call    message
+#endif
+1:     sti
+       hlt
+       jmp     1b
+
+boot_lba:
+       call    read_lba
+
+/*
+ * Check magic number for valid stage 2 bootcode
+ * then jump into it.
+ */
+pbr_read_ok:
+       cmpl    $X86_BOOT_MAGIC_1, bootxx_magic
+       set_err(ERR_NO_BOOTXX)
+       jnz     error
+
+       movl    %ebp, %esi                      /* %esi ptn base, %dl disk id */
+       movl    lba_sector + 4, %edi            /* %edi ptn base high */
+       jmp     $0, $bootxx                     /* our %cs may not be zero */
+
+/* Read disk using int13-extension parameter block */
+read_lba:
+       pusha
+       movw    $lba_info, %si                  /* ds:si is ctl block */
+       movb    $0x42, %ah
+do_read:
+       int     $0x13
+       popa
+
+       set_err(ERR_READ)
+       jc      error
+       ret
+
+/* Read using CHS */
+
+chs_read:
+       movw    $BOOTADDR, %bx                  /* es:bx is buffer */
+       pusha
+       movw    $0x200 + BOOTXX_SECTORS, %ax    /* command 2, xx sectors */
+       jmp     do_read
+
+#ifndef BOOT_FROM_FAT
+boot_gpt:
+       movl    (20+32+0)(%si), %ebp
+       movl    (20+32+4)(%si), %edi
+       movw    %cx, %ds
+       movl    %ebp, lba_sector + 0
+       movl    %edi, lba_sector + 4
+       movl    %ebp, %esi
+       jmp     boot_lba
+#endif
+
+_errtxt: .ascii        "Error "                        /* runs into newline... */
+_errcod: .byte 0                               /* ... if errcod set */
+_newline:
+       .asciz  "\r\n"
+
+#ifndef TERSE_ERROR
+ERR_READ:      .asciz  "read"
+ERR_NO_BOOTXX: .asciz  "no magic"
+ERR_PTN:       .asciz  "no slice"
+#ifndef NO_LBA_CHECK
+ERR_NO_LBA:    .asciz  "need LBA"
+#endif
+#endif
+
+/*
+ * I hate #including source files, but pbr_magic below has to be at
+ * the correct absolute address.
+ * Clearly this could be done with a linker script.
+ */
+
+#include <message.S>
+#if 0
+#include <dump_eax.S>
+#endif
+
+/* Control block for int-13 LBA read. */
+_lba_info:
+       .word   0x10                            /* control block length */
+       .word   BOOTXX_SECTORS                  /* sector count */
+       .word   BOOTADDR                        /* offset in segment */
+       .word   0                               /* segment */
+_lba_sector:
+       .quad   0                               /* sector # goes here... */
+
+/* Drive Serial Number */
+       . = _C_LABEL(start) + MBR_DSN_OFFSET
+       .long   0
+
+/* mbr_bootsel_magic (not used here) */
+       . = _C_LABEL(start) + MBR_BS_MAGIC_OFFSET
+       .word   0
+
+/*
+ * Provide empty MBR partition table.
+ * If this is installed as an MBR, the user can use fdisk(8) to create
+ * the correct partition table ...
+ */
+       . = _C_LABEL(start) + MBR_PART_OFFSET
+_pbr_part0:
+       .byte   0, 0, 0, 0, 0, 0, 0, 0  
+       .long   0, 0
+_pbr_part1:
+       .byte   0, 0, 0, 0, 0, 0, 0, 0  
+       .long   0, 0
+_pbr_part2:
+       .byte   0, 0, 0, 0, 0, 0, 0, 0  
+       .long   0, 0
+_pbr_part3:
+       .byte   0, 0, 0, 0, 0, 0, 0, 0  
+       .long   0, 0
+
+/*
+ * The magic comes last
+ */
+       . = _C_LABEL(start) + MBR_MAGIC_OFFSET
+pbr_magic:
+       .word   MBR_MAGIC
diff --git a/sys/arch/i386/stand/lib/Makefile b/sys/arch/i386/stand/lib/Makefile
new file mode 100644 (file)
index 0000000..a94e028
--- /dev/null
@@ -0,0 +1,80 @@
+#      $NetBSD: Makefile,v 1.35 2011/06/22 02:49:44 mrg Exp $
+
+S?=    ${.CURDIR}/../../../..
+
+LIB= i386
+NOPIC=# defined
+NOPROFILE=# defined
+
+I386_INCLUDE_DISK?= yes
+I386_INCLUDE_DOS?= no
+I386_INCLUDE_BUS?= no
+I386_INCLUDE_PS2?= yes
+
+AFLAGS.biosdelay.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosgetrtc.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosgetsystime.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosmca.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosmemps2.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosmem.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosmemx.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosreboot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosvbe.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.biosvideomode.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.bios_disk.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.bios_pci.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.comio.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.conio.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.dos_file.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.dump_eax.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.message.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.message32.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.pvcopy.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.putstr.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.putstr32.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+AFLAGS.realprot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
+
+CPPFLAGS= -I$S/lib/libsa ${I386CPPFLAGS} ${I386MISCCPPFLAGS}
+#CPPFLAGS+= -DDISK_DEBUG
+#CPPFLAGS+= -DNO_DISKLABEL
+#CPPFLAGS+= -DNO_GPT
+#CPPFLAGS+= -DSAVE_MEMORY
+
+SRCS= pcio.c conio.S comio.S comio_direct.c biosvideomode.S
+SRCS+= getsecs.c biosgetrtc.S biosdelay.S biosreboot.S gatea20.c
+SRCS+= biosmem.S getextmemx.c biosmemx.S printmemlist.c
+SRCS+= pread.c menuutils.c parseutils.c
+SRCS+= bootinfo.c bootinfo_biosgeom.c bootinfo_memmap.c
+SRCS+= startprog.S multiboot.S
+SRCS+= biosgetsystime.S cpufunc.S bootmenu.c
+SRCS+= realprot.S message.S message32.S dump_eax.S pvcopy.S putstr.S putstr32.S
+SRCS+= rasops.c vbe.c biosvbe.S
+.if (${I386_INCLUDE_DISK} == "yes")
+SRCS+= biosdisk.c biosdisk_ll.c bios_disk.S
+.endif
+.if (${I386_INCLUDE_DOS} == "yes")
+SRCS+= dosfile.c dos_file.S
+.endif
+.if (${I386_INCLUDE_DISK} == "yes") || (${I386_INCLUDE_DOS} == "yes")
+SRCS+= diskbuf.c
+.endif
+.if (${I386_INCLUDE_BUS} == "yes")
+SRCS+= biospci.c bios_pci.S isapnp.c isadma.c
+.endif
+.if (${I386_INCLUDE_PS2} == "yes")
+SRCS+= biosmca.S biosmemps2.S
+.endif
+
+.include <bsd.own.mk>
+.undef DESTDIR
+.include <bsd.lib.mk>
+
+lib${LIB}.o:: ${OBJS}
+       @echo building standard ${LIB} library
+       @rm -f lib${LIB}.o
+       @${LD} -r -o lib${LIB}.o `lorder ${OBJS} | tsort`
+
+# XXX
+.if ${HAVE_GCC} == 45
+COPTS.biosdisk.c+=     -fno-strict-aliasing
+.endif
diff --git a/sys/arch/i386/stand/lib/Makefile.inc b/sys/arch/i386/stand/lib/Makefile.inc
new file mode 100644 (file)
index 0000000..754a385
--- /dev/null
@@ -0,0 +1,55 @@
+#      $NetBSD: Makefile.inc,v 1.14 2011/05/26 12:56:30 joerg Exp $
+#
+#      Configuration variables (default values are below):
+#
+#      S       must be set to the top of the 'sys' tree.
+#      I386DST may be set to the location of the directory where library
+#              objects are to be built.  Defaults to ${.OBJDIR}/lib/i386.
+#      I386MISCCPPFLAGS
+#              Miscellaneous cpp flags to be passed to the library's Makefile
+#              when building.
+#      I386MISCMAKEFLAGS
+#              Miscellaneous flags to be passed to the library's Makefile when
+#              building.  See library's Makefile for more details about
+#              supported flags and their default values.
+
+# Default values:
+I386DST?=              ${.OBJDIR}/lib/i386
+
+#I386DIR=              $S/arch/i386/stand/lib
+I386LIB=               ${I386DST}/libi386.a
+
+CWARNFLAGS.clang+=     -Wno-tautological-compare
+
+I386MAKE= \
+       cd ${I386DIR} && MAKEOBJDIRPREFIX= && unset MAKEOBJDIRPREFIX && \
+           MAKEOBJDIR=${I386DST} ${MAKE} \
+           CC=${CC:Q} CFLAGS=${CFLAGS:Q} \
+           AS=${AS:Q} AFLAGS=${AFLAGS:Q} \
+           LD=${LD:Q} STRIP=${STRIP:Q} \
+           MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \
+           I386CPPFLAGS=${CPPFLAGS:S@^-I.@-I../../.@g:Q} \
+           I386MISCCPPFLAGS=${I386MISCCPPFLAGS:Q} \
+           ${I386MISCMAKEFLAGS}
+
+${I386LIB}:            .NOTMAIN __always_make_i386lib
+       @echo making sure the i386 library is up to date...
+       @${I386MAKE} libi386.a
+
+clean:                 .NOTMAIN cleani386lib
+cleani386lib:          .NOTMAIN
+       @echo cleaning the i386 library objects
+       @if [ -d "${I386DST}" ]; then ${I386MAKE} clean; fi
+
+cleandir distclean:    .NOTMAIN cleandiri386lib
+cleandiri386lib:       .NOTMAIN
+       @echo cleandiring the i386 library objects
+       @if [ -d "${I386DST}" ]; then ${I386MAKE} cleandir; fi
+
+dependall depend:      .NOTMAIN dependi386lib
+dependi386lib:         .NOTMAIN __always_make_i386lib
+       @echo depending the i386 library objects
+       @${I386MAKE} depend
+
+__always_make_i386lib: .NOTMAIN
+       @mkdir -p ${I386DST}
diff --git a/sys/arch/i386/stand/lib/bios_disk.S b/sys/arch/i386/stand/lib/bios_disk.S
new file mode 100644 (file)
index 0000000..578966e
--- /dev/null
@@ -0,0 +1,297 @@
+/*     $NetBSD: bios_disk.S,v 1.21 2011/06/16 13:27:59 joerg Exp $     */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/* extracted from netbsd:sys/arch/i386/boot/bios.S */
+
+#include <machine/asm.h>
+
+/*
+ * BIOS call "INT 0x13 Function 0x0" to reset the disk subsystem
+ *     Call with       %ah = 0x0
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+ENTRY(biosdisk_reset)
+       pusha
+
+       movb    %al, %dl        # device
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x0, %ah       # subfunction
+       int     $0x13
+       setc    %bl
+       movb    %ah, %bh        # save error code
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movzwl  %bx, %eax       # return value in %eax
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
+
+/*
+ * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+ *     Call with       %ah = 0x2
+ *                     %al = number of sectors
+ *                     %ch = cylinder
+ *                     %cl = sector
+ *                     %dh = head
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *                     %es:%bx = segment:offset of buffer
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ *
+ * biosdisk_read(dev, cyl, head, sect, count, buff_addr);
+ *
+ *  Note: On failure, you must reset the disk with biosdisk_reset() before
+ *        sending another command.
+ */
+ENTRY(biosdisk_read)
+       pusha
+
+       movb    44(%esp), %dh
+       movw    40(%esp), %cx
+       xchgb   %ch, %cl        # cylinder; the highest 2 bits of cyl is in %cl
+       rorb    $2, %cl
+       movb    48(%esp), %al
+       orb     %al, %cl
+       incb    %cl             # sector; sec starts from 1, not 0
+       movb    36(%esp), %dl   # device
+       movl    56(%esp), %ebx  # buffer address (may be >64k)
+       movb    52(%esp), %al   # number of sectors
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %bx
+       shrl    $4, %ebx        # max segment
+       mov     %ds, %si
+       add     %si, %bx
+       mov     %bx, %es        # %es:%bx now valid buffer address
+       pop     %bx
+       and     $0xf, %bx       # and min offset - to avoid overrun
+
+       movb    $0x2, %ah       # subfunction
+       int     $0x13
+       setc    %al             # error code is in %ah
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
+
+/*
+ * biosdisk_getinfo(int dev):  return a word that represents the
+ *     max number of sectors, heads and cylinders for this device
+ */
+ENTRY(biosdisk_getinfo)
+       push    %es
+       pusha
+
+       movb    %al, %dl                # diskinfo(drive #)
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %dx                     # save drive #
+       movb    $0x08, %ah              # ask for disk info
+       int     $0x13
+       pop     %bx                     # restore drive #
+       jnc     ok
+
+       testb   $0x80, %bl              # is it a hard disk?
+       jnz     ok
+
+       /*
+        * Urk.  Call failed.  It is not supported for floppies by old BIOS's.
+        * Guess it's a 15-sector floppy.  Initialize all the registers for
+        * documentation, although we only need head and sector counts.
+        */
+       xorw    %ax, %ax                # set status to success
+#      movb    %ah, %bh                # %bh = 0
+#      movb    $2, %bl                 # %bl bits 0-3 = drive type, 2 = 1.2M
+       movb    $79, %ch                # max track
+       movb    $15, %cl                # max sector
+       movb    $1, %dh                 # max head
+#      movb    $1, %dl                 # # floppy drives installed
+       # es:di = parameter table
+       # carry = 0
+
+ok:
+       calll   _C_LABEL(real_to_prot)  # back to protected mode
+       .code32
+
+       /* form a longword representing all this gunk */
+       shrl    $8, %eax                # clear unnecessary bits
+       shll    $24, %eax
+       shll    $16, %ecx               # do the same for %ecx
+       shrl    $8, %ecx
+       movb    %dh, %cl                # max head
+       orl     %ecx, %eax              # return value in %eax
+       movl    %eax, 28(%esp)
+
+       popa
+       pop     %es
+       ret
+
+/*
+ * int biosdisk_int13ext(int dev):
+ *     check for availibility of int13 extensions.
+ */
+ENTRY(biosdisk_int13ext)
+       pusha
+
+       movb    %al, %dl                # drive #
+       movw    $0x55aa, %bx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x41, %ah              # ask for disk info
+       int     $0x13
+       setnc   %dl
+
+       calll   _C_LABEL(real_to_prot)  # switch back
+       .code32
+
+       movzbl  %dl, %eax               # return value in %eax
+
+       cmpw    $0xaa55, %bx
+       sete    %dl
+       andb    %dl, %al
+
+       andb    %cl, %al
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
+
+/*
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ *     Call with       %ah = 0x42
+ *                     %ds:%si = parameter block (data buffer address
+ *                             must be a real mode physical address).
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+ENTRY(biosdisk_extread)
+       pusha
+
+       movl    %edx, %esi      # parameter block
+       movb    %al, %dl        # device
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %ds
+       movl    %esi, %eax
+       shrl    $4, %eax
+       movw    %ds, %bx
+       addw    %bx, %ax
+       movw    %ax, %ds
+       andw    $0xf, %si
+
+       movb    $0x42, %ah      # subfunction
+       int     $0x13
+       setc    %bl
+       movb    %ah, %bh        # save error code
+       pop     %ds
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movzwl  %bx, %eax       # return value in %eax
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
+
+ENTRY(biosdisk_getextinfo)
+       pusha
+
+       movl    %edx, %esi      # parameter block
+       movb    %al, %dl        # device
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %ds
+       movl    %esi, %eax
+       shrl    $4, %eax
+       andw    $0xf, %si
+       movw    %ds, %bx
+       addw    %bx, %ax
+       movw    %ax, %ds
+
+       movb    $0x48, %ah      # subfunction
+       int     $0x13
+       setc    %bl
+       pop     %ds
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movzbl  %bl, %eax       # return value in %eax
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/bios_pci.S b/sys/arch/i386/stand/lib/bios_pci.S
new file mode 100644 (file)
index 0000000..a62d20c
--- /dev/null
@@ -0,0 +1,214 @@
+/*     $NetBSD: bios_pci.S,v 1.6 2005/12/11 12:17:48 christos Exp $    */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* minimal calls to PCI BIOS */
+
+#include <machine/asm.h>
+
+#define        addr32  .byte 0x67
+#define        data32  .byte 0x66
+
+#define PCI_FUNCTION_ID 0xb1
+#define PCI_BIOS_PRESENT 0x01
+#define FIND_PCI_DEVICE 0x02
+#define READ_CONFIG_DWORD 0x0a
+#define WRITE_CONFIG_DWORD 0x0d
+
+/* int pcibios_present(int *signature)
+    return: AX from BIOS call, -1 on error
+    var param: EDX from BIOS call, must be signature "PCI "
+*/
+ENTRY(pcibios_present)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $PCI_FUNCTION_ID, %ah
+       movb    $PCI_BIOS_PRESENT, %al
+       int     $0x1a
+
+       jnc     ok1
+       movl    $-1, %ebx
+       jmp err1
+
+ok1:
+       xorl    %ebx, %ebx
+       mov     %ax, %bx
+err1:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    8(%ebp), %eax
+       movl    %edx, (%eax)
+
+       movl    %ebx, %eax              # return value in %eax
+
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/* int pcibios_finddev(int vendor, int device, int index, int *busdevfcn)
+    return: AH from BIOS call, -1 on error
+    var param: BX from BIOS call, contains bus/device/function
+*/
+ENTRY(pcibios_finddev)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %esi
+
+       movl    8(%ebp), %edx
+       movl    12(%ebp), %ecx
+       movl    16(%ebp), %esi
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $PCI_FUNCTION_ID, %ah
+       movb    $FIND_PCI_DEVICE, %al
+       int     $0x1a
+
+       jnc     ok2
+       movl    $-1, %edx
+       jmp err2
+
+ok2:
+       movl    $0,%edx
+       movb    %ah, %dl
+err2:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    20(%ebp), %eax
+       mov     %bx, (%eax)
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/* int pcibios_cfgread(int busdevfcn, int offset, int *value)
+    return: AH from BIOS call, -1 on error
+    var param: ECX from BIOS call, contains value read
+*/
+ENTRY(pcibios_cfgread)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %edi
+
+       movl    8(%ebp), %ebx
+       movl    12(%ebp), %edi
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $PCI_FUNCTION_ID, %ah
+       movb    $READ_CONFIG_DWORD, %al
+       int     $0x1a
+
+       jnc     ok3
+       movl    $-1, %edx
+       jmp err3
+
+ok3:
+       movl    $0,%edx
+       movb    %ah, %dl
+err3:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    16(%ebp), %eax
+       movl    %ecx, (%eax)
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/* int pcibios_cfgwrite(int busdevfcn, int offset, int value)
+    return: AH from BIOS call, -1 on error
+    var param: ECX from BIOS call, contains value read
+*/
+ENTRY(pcibios_cfgwrite)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %edi
+
+       movl    8(%ebp), %ebx
+       movl    12(%ebp), %edi
+       movl    16(%ebp), %ecx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $PCI_FUNCTION_ID, %ah
+       movb    $WRITE_CONFIG_DWORD, %al
+       int     $0x1a
+
+       jnc     ok4
+       movl    $-1, %edx
+       jmp err4
+
+ok4:
+       movl    $0,%edx
+       movb    %ah, %dl
+err4:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/biosdelay.S b/sys/arch/i386/stand/lib/biosdelay.S
new file mode 100644 (file)
index 0000000..e3925a2
--- /dev/null
@@ -0,0 +1,78 @@
+/*     $NetBSD: biosdelay.S,v 1.4 2005/12/11 12:17:48 christos Exp $   */
+
+/*
+ * Copyright (c) 1996, 1997
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/*
+ * BIOS call "INT 15H Function 86H" to sleep for a set number of microseconds
+ *     Call with       %ah = 0x86
+ *                     %cx = time interval (high)
+ *                     %dx = time interval (low)
+ *     Return:
+ *             If error
+ *                     CF  = set
+ *             else
+ *                     CF  = clear
+ */
+ENTRY(delay)
+       pushl   %ebp
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+
+       movw    20(%esp), %dx
+       movw    22(%esp), %cx
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movb    $0x86, %ah
+       int     $0x15
+       setnc   %ah
+
+       movb    %ah, %bl        # real_to_prot uses %eax
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       xorl    %eax, %eax
+       movb    %bl, %al
+
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/biosdisk.c b/sys/arch/i386/stand/lib/biosdisk.c
new file mode 100644 (file)
index 0000000..13701c7
--- /dev/null
@@ -0,0 +1,808 @@
+/*     $NetBSD: biosdisk.c,v 1.39 2011/09/21 08:57:12 gsutre Exp $     */
+
+/*
+ * Copyright (c) 1996, 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * raw BIOS disk device for libsa.
+ * needs lowlevel parts from bios_disk.S and biosdisk_ll.c
+ * partly from netbsd:sys/arch/i386/boot/disk.c
+ * no bad144 handling!
+ *
+ * A lot of this must match sys/kern/subr_disk_mbr.c
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+#define FSTYPENAMES
+#endif
+
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include <sys/types.h>
+#include <sys/md5.h>
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
+#include <sys/uuid.h>
+
+#include <fs/cd9660/iso.h>
+
+#include <lib/libsa/saerrno.h>
+#include <machine/cpu.h>
+
+#include "libi386.h"
+#include "biosdisk_ll.h"
+#include "biosdisk.h"
+#ifdef _STANDALONE
+#include "bootinfo.h"
+#endif
+
+#define BUFSIZE        2048    /* must be large enough for a CD sector */
+
+#define BIOSDISKNPART 26
+
+struct biosdisk {
+       struct biosdisk_ll ll;
+       daddr_t         boff;
+       char            buf[BUFSIZE];
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+       struct {
+               daddr_t offset;
+               daddr_t size;
+               int     fstype;
+       } part[BIOSDISKNPART];
+#endif
+};
+
+#ifndef NO_GPT
+const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME;
+const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS;
+const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS;
+const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP;
+#endif /* NO_GPT */
+
+#ifdef _STANDALONE
+static struct btinfo_bootdisk bi_disk;
+static struct btinfo_bootwedge bi_wedge;
+#endif
+
+#define        RF_PROTECTED_SECTORS    64      /* XXX refer to <.../rf_optnames.h> */
+
+int
+biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
+                 void *buf, size_t *rsize)
+{
+       struct biosdisk *d;
+       int blks, frag;
+
+       if (flag != F_READ)
+               return EROFS;
+
+       d = (struct biosdisk *) devdata;
+
+       if (d->ll.type == BIOSDISK_TYPE_CD)
+               dblk = dblk * DEV_BSIZE / ISO_DEFAULT_BLOCK_SIZE;
+
+       dblk += d->boff;
+
+       blks = size / d->ll.secsize;
+       if (blks && readsects(&d->ll, dblk, blks, buf, 0)) {
+               if (rsize)
+                       *rsize = 0;
+               return EIO;
+       }
+
+       /* needed for CD */
+       frag = size % d->ll.secsize;
+       if (frag) {
+               if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) {
+                       if (rsize)
+                               *rsize = blks * d->ll.secsize;
+                       return EIO;
+               }
+               memcpy(buf + blks * d->ll.secsize, d->buf, frag);
+       }
+
+       if (rsize)
+               *rsize = size;
+       return 0;
+}
+
+static struct biosdisk *
+alloc_biosdisk(int biosdev)
+{
+       struct biosdisk *d;
+
+       d = alloc(sizeof(*d));
+       if (d == NULL)
+               return NULL;
+       memset(d, 0, sizeof(*d));
+
+       d->ll.dev = biosdev;
+       if (set_geometry(&d->ll, NULL)) {
+#ifdef DISK_DEBUG
+               printf("no geometry information\n");
+#endif
+               dealloc(d, sizeof(*d));
+               return NULL;
+       }
+       return d;
+}
+
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+static void
+md5(void *hash, const void *data, size_t len)
+{
+       MD5_CTX ctx;
+
+       MD5Init(&ctx);
+       MD5Update(&ctx, data, len);
+       MD5Final(hash, &ctx);
+
+       return;
+}
+#endif
+
+#ifndef NO_GPT
+static bool
+guid_is_nil(const struct uuid *u)
+{
+       static const struct uuid nil = { .time_low = 0 };
+       return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false);
+}
+
+static bool
+guid_is_equal(const struct uuid *a, const struct uuid *b)
+{
+       return (memcmp(a, b, sizeof(*a)) == 0 ? true : false);
+}
+
+static int
+check_gpt(struct biosdisk *d, daddr_t sector)
+{
+       struct gpt_hdr gpth;
+       const struct gpt_ent *ep;
+       const struct uuid *u;
+       daddr_t entblk;
+       size_t size;
+       uint32_t crc;
+       int sectors;
+       int entries;
+       int entry;
+       int i, j;
+
+       /* read in gpt_hdr sector */
+       if (readsects(&d->ll, sector, 1, d->buf, 1)) {
+#ifdef DISK_DEBUG
+               printf("Error reading GPT header at %"PRId64"\n", sector);
+#endif
+               return EIO;
+       }
+
+       gpth = *(const struct gpt_hdr *)d->buf;
+
+       if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig)))
+               return -1;
+
+       crc = gpth.hdr_crc_self;
+       gpth.hdr_crc_self = 0;
+       gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE);
+       if (gpth.hdr_crc_self != crc) {
+               return -1;
+       }
+
+       if (gpth.hdr_lba_self != sector)
+               return -1;
+
+#ifdef _STANDALONE
+       bi_wedge.matchblk = sector;
+       bi_wedge.matchnblks = 1;
+
+       md5(bi_wedge.matchhash, d->buf, d->ll.secsize);
+#endif
+
+       sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */
+       entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */
+       entblk = gpth.hdr_lba_table;
+       crc = crc32(0, NULL, 0);
+
+       j = 0;
+       ep = (const struct gpt_ent *)d->buf;
+
+       for (entry = 0; entry < gpth.hdr_entries; entry += entries) {
+               size = MIN(sizeof(d->buf),
+                   (gpth.hdr_entries - entry) * gpth.hdr_entsz);
+               entries = size / gpth.hdr_entsz;
+               sectors = roundup(size, d->ll.secsize) / d->ll.secsize;
+               if (readsects(&d->ll, entblk, sectors, d->buf, 1))
+                       return -1;
+               entblk += sectors;
+               crc = crc32(crc, (const void *)d->buf, size);
+
+               for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) {
+                       u = (const struct uuid *)ep[i].ent_type;
+                       if (!guid_is_nil(u)) {
+                               d->part[j].offset = ep[i].ent_lba_start;
+                               d->part[j].size = ep[i].ent_lba_end -
+                                   ep[i].ent_lba_start + 1;
+                               if (guid_is_equal(u, &GET_nbsd_ffs))
+                                       d->part[j].fstype = FS_BSDFFS;
+                               else if (guid_is_equal(u, &GET_nbsd_lfs))
+                                       d->part[j].fstype = FS_BSDLFS;
+                               else if (guid_is_equal(u, &GET_nbsd_raid))
+                                       d->part[j].fstype = FS_RAID;
+                               else if (guid_is_equal(u, &GET_nbsd_swap))
+                                       d->part[j].fstype = FS_SWAP;
+                               else
+                                       d->part[j].fstype = FS_OTHER;
+                       }
+               }
+
+       }
+
+       if (crc != gpth.hdr_crc_table) {
+#ifdef DISK_DEBUG      
+               printf("GPT table CRC invalid\n");
+#endif
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+read_gpt(struct biosdisk *d)
+{
+       struct biosdisk_extinfo ed;
+       daddr_t gptsector[2];
+       int i, error;
+
+       if (d->ll.type != BIOSDISK_TYPE_HD)
+               /* No GPT on floppy and CD */
+               return -1;
+
+       gptsector[0] = GPT_HDR_BLKNO;
+       if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) {
+               gptsector[1] = ed.totsec - 1;
+               d->ll.secsize = ed.sbytes;
+       } else {
+#ifdef DISK_DEBUG
+               printf("Unable to determine extended disk geometry - "
+                       "using CHS\n");
+#endif
+               /* at least try some other reasonable values then */
+               gptsector[1] = d->ll.chs_sectors - 1;
+       }
+
+       /*
+        * Use any valid GPT available, do not require both GPTs to be valid
+        */
+       for (i = 0; i < __arraycount(gptsector); i++) {
+               error = check_gpt(d, gptsector[i]);
+               if (error == 0)
+                       break;
+       }
+
+       if (i >= __arraycount(gptsector)) {
+               memset(d->part, 0, sizeof(d->part));
+               return -1;
+       }
+
+#ifdef DISK_DEBUG
+       printf("using %s GPT\n", (i == 0) ? "primary" : "secondary");
+#endif
+       return 0;
+}
+#endif /* !NO_GPT */
+
+#ifndef NO_DISKLABEL
+static void
+ingest_label(struct biosdisk *d, struct disklabel *lp)
+{
+       int part;
+
+       memset(d->part, 0, sizeof(d->part));
+
+       for (part = 0; part < lp->d_npartitions; part++) {
+               if (lp->d_partitions[part].p_size == 0)
+                       continue;
+               if (lp->d_partitions[part].p_fstype == FS_UNUSED)
+                       continue;
+               d->part[part].fstype = lp->d_partitions[part].p_fstype;
+               d->part[part].offset = lp->d_partitions[part].p_offset;
+               d->part[part].size = lp->d_partitions[part].p_size;
+       }
+}
+       
+static int
+check_label(struct biosdisk *d, daddr_t sector)
+{
+       struct disklabel *lp;
+
+       /* find partition in NetBSD disklabel */
+       if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) {
+#ifdef DISK_DEBUG
+               printf("Error reading disklabel\n");
+#endif
+               return EIO;
+       }
+       lp = (struct disklabel *) (d->buf + LABELOFFSET);
+       if (lp->d_magic != DISKMAGIC || dkcksum(lp)) {
+#ifdef DISK_DEBUG
+               printf("warning: no disklabel in sector %"PRId64"\n", sector);
+#endif
+               return -1;
+       }
+
+       ingest_label(d, lp);
+
+#ifdef _STANDALONE
+       bi_disk.labelsector = sector + LABELSECTOR;
+       bi_disk.label.type = lp->d_type;
+       memcpy(bi_disk.label.packname, lp->d_packname, 16);
+       bi_disk.label.checksum = lp->d_checksum;
+
+       bi_wedge.matchblk = sector + LABELSECTOR;
+       bi_wedge.matchnblks = 1;
+
+       md5(bi_wedge.matchhash, d->buf, d->ll.secsize);
+#endif
+
+       return 0;
+}
+
+static int
+read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl,
+                       int this_ext, daddr_t sector)
+{
+       struct mbr_partition mbr[MBR_PART_COUNT];
+       int i;
+       int typ;
+       struct partition *p;
+
+       if (readsects(&d->ll, sector, 1, d->buf, 0)) {
+#ifdef DISK_DEBUG
+               printf("Error reading MFS sector %d\n", sector);
+#endif
+               return EIO;
+       }
+       if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) {
+               return -1;
+       }
+       memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, sizeof(mbr));
+       for (i = 0; i < MBR_PART_COUNT; i++) {
+               typ = mbr[i].mbrp_type;
+               if (typ == 0)
+                       continue;
+               sector = this_ext + mbr[i].mbrp_start;
+               if (dflt_lbl->d_npartitions >= MAXPARTITIONS)
+                       continue;
+               p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++];
+               p->p_offset = sector;
+               p->p_size = mbr[i].mbrp_size;
+               p->p_fstype = xlat_mbr_fstype(typ);
+       }
+       return 0;
+}
+
+static int
+read_label(struct biosdisk *d)
+{
+       struct disklabel dflt_lbl;
+       struct mbr_partition mbr[MBR_PART_COUNT];
+       struct partition *p;
+       int sector, i;
+       int error;
+       int typ;
+       int ext_base, this_ext, next_ext;
+#ifdef COMPAT_386BSD_MBRPART
+       int sector_386bsd = -1;
+#endif
+
+       memset(&dflt_lbl, 0, sizeof(dflt_lbl));
+       dflt_lbl.d_npartitions = 8;
+
+       d->boff = 0;
+
+       if (d->ll.type != BIOSDISK_TYPE_HD)
+               /* No label on floppy and CD */
+               return -1;
+
+       /*
+        * find NetBSD Partition in DOS partition table
+        * XXX check magic???
+        */
+       ext_base = 0;
+       next_ext = 0;
+       for (;;) {
+               this_ext = ext_base + next_ext;
+               next_ext = 0;
+               if (readsects(&d->ll, this_ext, 1, d->buf, 0)) {
+#ifdef DISK_DEBUG
+                       printf("error reading MBR sector %d\n", this_ext);
+#endif
+                       return EIO;
+               }
+               memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts,
+                      sizeof(mbr));
+               /* Look for NetBSD partition ID */
+               for (i = 0; i < MBR_PART_COUNT; i++) {
+                       typ = mbr[i].mbrp_type;
+                       if (typ == 0)
+                               continue;
+                       sector = this_ext + mbr[i].mbrp_start;
+#ifdef DISK_DEBUG
+                       printf("ptn type %d in sector %d\n", typ, sector);
+#endif
+                        if (typ == MBR_PTYPE_MINIX_14B) {
+                               if (!read_minix_subp(d, &dflt_lbl,
+                                                  this_ext, sector)) {
+                                       /* Don't add "container" partition */
+                                       continue;
+                               }
+                       }
+                       if (typ == MBR_PTYPE_NETBSD) {
+                               error = check_label(d, sector);
+                               if (error >= 0)
+                                       return error;
+                       }
+                       if (MBR_IS_EXTENDED(typ)) {
+                               next_ext = mbr[i].mbrp_start;
+                               continue;
+                       }
+#ifdef COMPAT_386BSD_MBRPART
+                       if (this_ext == 0 && typ == MBR_PTYPE_386BSD)
+                               sector_386bsd = sector;
+#endif
+                       if (this_ext != 0) {
+                               if (dflt_lbl.d_npartitions >= MAXPARTITIONS)
+                                       continue;
+                               p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++];
+                       } else
+                               p = &dflt_lbl.d_partitions[i];
+                       p->p_offset = sector;
+                       p->p_size = mbr[i].mbrp_size;
+                       p->p_fstype = xlat_mbr_fstype(typ);
+               }
+               if (next_ext == 0)
+                       break;
+               if (ext_base == 0) {
+                       ext_base = next_ext;
+                       next_ext = 0;
+               }
+       }
+
+       sector = 0;
+#ifdef COMPAT_386BSD_MBRPART
+       if (sector_386bsd != -1) {
+               printf("old BSD partition ID!\n");
+               sector = sector_386bsd;
+       }
+#endif
+
+       /*
+        * One of two things:
+        *      1. no MBR
+        *      2. no NetBSD partition in MBR
+        *
+        * We simply default to "start of disk" in this case and
+        * press on.
+        */
+       error = check_label(d, sector);
+       if (error >= 0)
+               return error;
+
+       /*
+        * Nothing at start of disk, return info from mbr partitions.
+        */
+       /* XXX fill it to make checksum match kernel one */
+       dflt_lbl.d_checksum = dkcksum(&dflt_lbl);
+       ingest_label(d, &dflt_lbl);
+       return 0;
+}
+#endif /* NO_DISKLABEL */
+
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+static int
+read_partitions(struct biosdisk *d)
+{
+       int error;
+
+       error = -1;
+
+#ifndef NO_GPT
+       error = read_gpt(d);
+       if (error == 0)
+               return 0;
+
+#endif
+#ifndef NO_DISKLABEL
+       error = read_label(d);
+       
+#endif
+       return error;
+}
+#endif
+
+void
+biosdisk_probe(void)
+{
+       struct biosdisk d;
+       struct biosdisk_extinfo ed;
+       uint64_t size;
+       int first;
+       int i;
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+       int part;
+#endif
+
+       for (i = 0; i < MAX_BIOSDISKS + 2; i++) {
+               first = 1;
+               memset(&d, 0, sizeof(d));
+               memset(&ed, 0, sizeof(ed));
+               if (i >= MAX_BIOSDISKS)
+                       d.ll.dev = 0x00 + i - MAX_BIOSDISKS;    /* fd */
+               else
+                       d.ll.dev = 0x80 + i;                    /* hd/cd */
+               if (set_geometry(&d.ll, &ed))
+                       continue;
+               printf("disk ");
+               switch (d.ll.type) {
+               case BIOSDISK_TYPE_CD:
+                       printf("cd0\n  cd0a\n");
+                       break;
+               case BIOSDISK_TYPE_FD:
+                       printf("fd%d\n", d.ll.dev & 0x7f);
+                       printf("  fd%da\n", d.ll.dev & 0x7f);
+                       break;
+               case BIOSDISK_TYPE_HD:
+                       printf("hd%d", d.ll.dev & 0x7f);
+                       if (d.ll.flags & BIOSDISK_INT13EXT) {
+                               printf(" size ");
+                               size = ed.totsec * ed.sbytes;
+                               if (size >= (10ULL * 1024 * 1024 * 1024))
+                                       printf("%"PRIu64" GB",
+                                           size / (1024 * 1024 * 1024));
+                               else
+                                       printf("%"PRIu64" MB",
+                                           size / (1024 * 1024));
+                       }
+                       printf("\n");
+                       break;
+               }
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+               if (d.ll.type != BIOSDISK_TYPE_HD)
+                       continue;
+
+               if (read_partitions(&d) != 0)
+                       continue;
+                       
+               for (part = 0; part < BIOSDISKNPART; part++) {
+                       if (d.part[part].size == 0)
+                               continue;
+                       if (d.part[part].fstype == FS_UNUSED)
+                               continue;
+                       if (first) {
+                               printf(" ");
+                               first = 0;
+                       }
+                       printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a');
+                       if (d.part[part].fstype < FSMAXTYPES)
+                               printf("%s",
+                                 fstypenames[d.part[part].fstype]);
+                       else
+                               printf("%d", d.part[part].fstype);
+                       printf(")");
+               }
+#endif
+               if (first == 0)
+                       printf("\n");
+       }
+}
+
+/* Determine likely partition for possible sector number of dos
+ * partition.
+ */
+
+int
+biosdisk_findpartition(int biosdev, daddr_t sector)
+{
+#if defined(NO_DISKLABEL) && defined(NO_GPT)
+       return 0;
+#else
+       struct biosdisk *d;
+       int partition = 0;
+#ifdef DISK_DEBUG
+       printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector);
+#endif
+
+       /* Look for netbsd partition that is the dos boot one */
+       d = alloc_biosdisk(biosdev);
+       if (d == NULL)
+               return 0;
+
+       if (read_partitions(d) == 0) {
+               for (partition = (BIOSDISKNPART-1); --partition;) {
+                       if (d->part[partition].fstype == FS_UNUSED)
+                               continue;
+                       if (d->part[partition].offset == sector)
+                               break;
+               }
+       }
+
+       dealloc(d, sizeof(*d));
+       return partition;
+#endif /* NO_DISKLABEL && NO_GPT */
+}
+
+#ifdef _STANDALONE
+static void
+add_biosdisk_bootinfo(void)
+{
+       static bool done;
+
+       if (bootinfo == NULL) {
+               done = false;
+               return;
+       }
+       
+       if (done)
+               return;
+
+       BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk));
+       BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge));
+
+       done = true;
+
+       return;
+}
+
+#endif
+
+int
+biosdisk_open(struct open_file *f, ...)
+/* struct open_file *f, int biosdev, int partition */
+{
+       va_list ap;
+       struct biosdisk *d;
+       int biosdev;
+       int partition;
+       int error = 0;
+
+       va_start(ap, f);
+       biosdev = va_arg(ap, int);
+       d = alloc_biosdisk(biosdev);
+       if (d == NULL) {
+               error = ENXIO;
+               goto out;
+       }
+
+       partition = va_arg(ap, int);
+#ifdef _STANDALONE
+       bi_disk.biosdev = d->ll.dev;
+       bi_disk.partition = partition;
+       bi_disk.labelsector = -1;
+
+       bi_wedge.biosdev = d->ll.dev;
+       bi_wedge.matchblk = -1;
+#endif
+
+#if !defined(NO_DISKLABEL) || !defined(NO_GPT)
+       error = read_partitions(d);
+       if (error == -1) {
+               error = 0;
+               goto nolabel;
+       }
+       if (error)
+               goto out;
+
+       if (partition >= BIOSDISKNPART ||
+           d->part[partition].fstype == FS_UNUSED) {
+#ifdef DISK_DEBUG
+               printf("illegal partition\n");
+#endif
+               error = EPART;
+               goto out;
+       }
+
+       d->boff = d->part[partition].offset;
+
+       if (d->part[partition].fstype == FS_RAID)
+               d->boff += RF_PROTECTED_SECTORS;
+
+#ifdef _STANDALONE
+       bi_wedge.startblk = d->part[partition].offset;
+       bi_wedge.nblks = d->part[partition].size;
+#endif
+
+nolabel:
+#endif
+#ifdef DISK_DEBUG
+       printf("partition @%"PRId64"\n", d->boff);
+#endif
+
+#ifdef _STANDALONE
+       add_biosdisk_bootinfo();
+#endif
+
+       f->f_devdata = d;
+out:
+        va_end(ap);
+       if (error)
+               dealloc(d, sizeof(*d));
+       return error;
+}
+
+#ifndef LIBSA_NO_FS_CLOSE
+int
+biosdisk_close(struct open_file *f)
+{
+       struct biosdisk *d = f->f_devdata;
+
+       /* let the floppy drive go off */
+       if (d->ll.type == BIOSDISK_TYPE_FD)
+               wait_sec(3);    /* 2s is enough on all PCs I found */
+
+       dealloc(d, sizeof(*d));
+       f->f_devdata = NULL;
+       return 0;
+}
+#endif
+
+int
+biosdisk_ioctl(struct open_file *f, u_long cmd, void *arg)
+{
+       return EIO;
+}
diff --git a/sys/arch/i386/stand/lib/biosdisk.h b/sys/arch/i386/stand/lib/biosdisk.h
new file mode 100644 (file)
index 0000000..216a0cf
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: biosdisk.h,v 1.8 2010/12/24 20:36:51 jakllsch Exp $    */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int biosdisk_strategy(void *, int, daddr_t, size_t, void *, size_t *);
+int biosdisk_open(struct open_file *, ...);
+int biosdisk_close(struct open_file *);
+int biosdisk_ioctl(struct open_file *, u_long, void *);
+int biosdisk_findpartition(int, daddr_t);
diff --git a/sys/arch/i386/stand/lib/biosdisk_ll.c b/sys/arch/i386/stand/lib/biosdisk_ll.c
new file mode 100644 (file)
index 0000000..2eafbc9
--- /dev/null
@@ -0,0 +1,319 @@
+/*     $NetBSD: biosdisk_ll.c,v 1.31 2011/02/21 02:58:02 jakllsch Exp $         */
+
+/*-
+ * Copyright (c) 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bang Jun-Young.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Matthias Drochner.
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * shared by bootsector startup (bootsectmain) and biosdisk.c
+ * needs lowlevel parts from bios_disk.S
+ */
+
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include "biosdisk_ll.h"
+#include "diskbuf.h"
+#include "libi386.h"
+
+static int do_read(struct biosdisk_ll *, daddr_t, int, char *);
+
+/*
+ * we get from get_diskinfo():
+ *      %ah      %ch      %cl      %dh (registers after int13/8), ie
+ * xxxxxxxx cccccccc CCssssss hhhhhhhh
+ */
+#define STATUS(di)     ((di)>>24)
+#define SPT(di)                (((di)>>8)&0x3f)
+#define HEADS(di)      (((di)&0xff)+1)
+#define CYL(di)                (((((di)>>16)&0xff)|(((di)>>6)&0x300))+1)
+
+#ifndef BIOSDISK_RETRIES
+#define BIOSDISK_RETRIES 5
+#endif
+
+int
+set_geometry(struct biosdisk_ll *d, struct biosdisk_extinfo *ed)
+{
+       int diskinfo;
+
+       diskinfo = biosdisk_getinfo(d->dev);
+       d->sec = SPT(diskinfo);
+       d->head = HEADS(diskinfo);
+       d->cyl = CYL(diskinfo);
+       d->chs_sectors = d->sec * d->head * d->cyl;
+
+       if (d->dev >= 0x80 + get_harddrives()) {
+               d->secsize = 2048;
+               d->type = BIOSDISK_TYPE_CD;
+       } else {
+               d->secsize = 512;
+               if (d->dev & 0x80)
+                       d->type = BIOSDISK_TYPE_HD;
+               else
+                       d->type = BIOSDISK_TYPE_FD;
+       }
+
+       /*
+        * Some broken BIOSes such as one found on Soltek SL-75DRV2 report
+        * that they don't support int13 extension for CD-ROM drives while
+        * they actually do. As a workaround, if the boot device is a CD we
+        * assume that the extension is available. Note that only very old
+        * BIOSes don't support the extended mode, and they don't work with
+        * ATAPI CD-ROM drives, either. So there's no problem.
+        */
+       d->flags = 0;
+       if (d->type == BIOSDISK_TYPE_CD ||
+           (d->type == BIOSDISK_TYPE_HD && biosdisk_int13ext(d->dev))) {
+               d->flags |= BIOSDISK_INT13EXT;
+               if (ed != NULL) {
+                       ed->size = sizeof(*ed);
+                       if (biosdisk_getextinfo(d->dev, ed) != 0)
+                               return -1;
+               }
+       }
+
+       /*
+        * If the drive is 2.88MB floppy drive, check that we can actually
+        * read sector >= 18. If not, assume 1.44MB floppy disk.
+        */
+       if (d->type == BIOSDISK_TYPE_FD && SPT(diskinfo) == 36) {
+               char buf[512];
+
+               if (biosdisk_read(d->dev, 0, 0, 18, 1, buf)) {
+                       d->sec = 18;
+                       d->chs_sectors /= 2;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Global shared "diskbuf" is used as read ahead buffer.  For reading from
+ * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that
+ * this buffer doesn't cross a 64K DMA boundary.
+ */
+static int      ra_dev;
+static daddr_t  ra_end;
+static daddr_t  ra_first;
+
+/*
+ * Because some older BIOSes have bugs in their int13 extensions, we
+ * only try to use the extended read if the I/O request can't be addressed
+ * using CHS.
+ *
+ * Of course, some BIOSes have bugs in ths CHS read, such as failing to
+ * function properly if the MBR table has a different geometry than the
+ * BIOS would generate internally for the device in question, and so we
+ * provide a way to force the extended on hard disks via a compile-time
+ * option.
+ */
+#if defined(FORCE_INT13EXT)
+#define        NEED_INT13EXT(d, dblk, num)                             \
+       (((d)->dev & 0x80) != 0)
+#else
+#define        NEED_INT13EXT(d, dblk, num)                             \
+       (((d)->type == BIOSDISK_TYPE_CD) ||                     \
+        ((d)->type == BIOSDISK_TYPE_HD &&                      \
+         ((dblk) + (num)) >= (d)->chs_sectors))
+#endif
+
+static int
+do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf)
+{
+
+       if (NEED_INT13EXT(d, dblk, num)) {
+               struct {
+                       int8_t size;
+                       int8_t resvd;
+                       int16_t cnt;
+                       int16_t off;
+                       int16_t seg;
+                       int64_t sec;
+               } ext;
+
+               if (!(d->flags & BIOSDISK_INT13EXT))
+                       return -1;
+               ext.size = sizeof(ext);
+               ext.resvd = 0;
+               ext.cnt = num;
+               /* seg:off of physical address */
+               ext.off = (int)buf & 0xf;
+               ext.seg = vtophys(buf) >> 4;
+               ext.sec = dblk;
+
+               if (biosdisk_extread(d->dev, &ext)) {
+                       (void)biosdisk_reset(d->dev);
+                       return -1;
+               }
+
+               return ext.cnt;
+       } else {
+               int cyl, head, sec, nsec, spc, dblk32;
+
+               dblk32 = (int)dblk;
+               spc = d->head * d->sec;
+               cyl = dblk32 / spc;
+               head = (dblk32 % spc) / d->sec;
+               sec = dblk32 % d->sec;
+               nsec = d->sec - sec;
+
+               if (nsec > num)
+                       nsec = num;
+
+               if (biosdisk_read(d->dev, cyl, head, sec, nsec, buf)) {
+                       (void)biosdisk_reset(d->dev);
+                       return -1;
+               }
+
+               return nsec;
+       }
+}
+
+/*
+ * NB if 'cold' is set below not all of the program is loaded, so
+ * mustn't use data segment, bss, call library functions or do read-ahead.
+ */
+int
+readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold)
+{
+#ifdef BOOTXX
+#define cold 1         /* collapse out references to diskbufp */
+#endif
+       while (num) {
+               int nsec;
+
+               /* check for usable data in read-ahead buffer */
+               if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev
+                   || dblk < ra_first || dblk >= ra_end) {
+
+                       /* no, read from disk */
+                       char *trbuf;
+                       int maxsecs;
+                       int retries = BIOSDISK_RETRIES;
+
+                       if (cold) {
+                               /* transfer directly to buffer */
+                               trbuf = buf;
+                               maxsecs = num;
+                       } else {
+                               /* fill read-ahead buffer */
+                               trbuf = alloc_diskbuf(0); /* no data yet */
+                               maxsecs = DISKBUFSIZE / d->secsize;
+                       }
+
+                       while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) {
+#ifdef DISK_DEBUG
+                               if (!cold)
+                                       printf("read error dblk %"PRId64"-%"PRId64"\n",
+                                           dblk, (dblk + maxsecs - 1));
+#endif
+                               if (--retries >= 0)
+                                       continue;
+                               return -1;      /* XXX cannot output here if
+                                                * (cold) */
+                       }
+                       if (!cold) {
+                               ra_dev = d->dev;
+                               ra_first = dblk;
+                               ra_end = dblk + nsec;
+                               diskbuf_user = &ra_dev;
+                       }
+               } else          /* can take blocks from end of read-ahead
+                                * buffer */
+                       nsec = ra_end - dblk;
+
+               if (!cold) {
+                       /* copy data from read-ahead to user buffer */
+                       if (nsec > num)
+                               nsec = num;
+                       memcpy(buf,
+                              diskbufp + (dblk - ra_first) * d->secsize,
+                              nsec * d->secsize);
+               }
+               buf += nsec * d->secsize;
+               num -= nsec;
+               dblk += nsec;
+       }
+
+       return 0;
+}
+
+/*
+ * Return the number of hard disk drives.
+ */
+int
+get_harddrives(void)
+{
+       /*
+        * Some BIOSes are buggy so that they return incorrect number
+        * of hard drives with int13/ah=8. We read a byte at 0040:0075
+        * instead, which is known to be always correct.
+        */
+       int n = 0;
+
+       pvbcopy((void *)0x475, &n, 1);
+
+       return n;
+}
diff --git a/sys/arch/i386/stand/lib/biosdisk_ll.h b/sys/arch/i386/stand/lib/biosdisk_ll.h
new file mode 100644 (file)
index 0000000..45ac589
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: biosdisk_ll.h,v 1.15 2007/12/25 18:33:34 perry Exp $    */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Matthias Drochner.
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * shared by bootsector startup (bootsectmain) and biosdisk.c needs lowlevel
+ * parts from bios_disk.S
+ */
+
+/*
+ * Beware that bios_disk.S relies on the offsets of the structure
+ * members.
+ */
+struct biosdisk_ll {
+       int             dev;            /* BIOS device number */
+       int             type;           /* device type; see below */
+       int             sec, head, cyl; /* geometry */
+       int             flags;          /* see below */
+       int             chs_sectors;    /* # of sectors addressable by CHS */
+       int             secsize;        /* bytes per sector */
+};
+#define        BIOSDISK_INT13EXT       1       /* BIOS supports int13 extension */
+
+#define BIOSDISK_TYPE_FD       0
+#define BIOSDISK_TYPE_HD       1
+#define BIOSDISK_TYPE_CD       2
+
+/*
+ * Version 1.x drive parameters from int13 extensions
+ * - should be supported by every BIOS that supports the extensions.
+ * Version 3.x parameters allow the drives to be matched properly
+ * - but are much less likely to be supported.
+ */
+
+struct biosdisk_extinfo {
+       uint16_t        size;           /* size of buffer, set on call */
+       uint16_t        flags;          /* flags, see below */
+       uint32_t        cyl;            /* # of physical cylinders */
+       uint32_t        head;           /* # of physical heads */
+       uint32_t        sec;            /* # of physical sectors per track */
+       uint64_t        totsec;         /* total number of sectors */
+       uint16_t        sbytes;         /* # of bytes per sector */
+#if defined(BIOSDISK_EXTINFO_V2) || defined(BIOSDISK_EXTINFO_V3)
+       /* v2.0 extensions */
+       uint32_t        edd_cfg;        /* EDD configuration parameters */
+#if defined(BIOSDISK_EXTINFO_V3)
+       /* v3.0 extensions */
+       uint16_t        devpath_sig;    /* 0xbedd if path info present */
+#define EXTINFO_DEVPATH_SIGNATURE      0xbedd
+       uint8_t         devpath_len;    /* length from devpath_sig */
+       uint8_t         fill21[3];
+       char            host_bus[4];    /* Probably "ISA" or "PCI" */
+       char            iface_type[8];  /* "ATA", "ATAPI", "SCSI" etc */
+       union {
+               uint8_t         ip_8[8];
+               uint16_t        ip_16[4];
+               uint32_t        ip_32[2];
+               uint64_t        ip_64[1];
+       } interface_path;
+#define        ip_isa_iobase   ip_16[0];       /* iobase for ISA bus */
+#define        ip_pci_bus      ip_8[0];        /* PCI bus number */
+#define        ip_pci_device   ip_8[1];        /* PCI device number */
+#define        ip_pci_function ip_8[2];        /* PCI function number */
+       union {
+               uint8_t         dp_8[8];
+               uint16_t        dp_16[4];
+               uint32_t        dp_32[2];
+               uint64_t        dp_64[1];
+       } device_path;
+#define        dp_ata_slave    dp_8[0];
+#define        dp_atapi_slave  dp_8[0];
+#define        dp_atapi_lun    dp_8[1];
+#define        dp_scsi_lun     dp_8[0];
+#define        dp_firewire_guid dp_64[0];
+#define        dp_fibrechnl_wwn dp_64[0];
+       uint8_t         fill40[1];
+       uint8_t         checksum;       /* byte sum from dev_path_sig is 0 */
+#endif /* BIOSDISK_EXTINFO_V3 */
+#endif /* BIOSDISK_EXTINFO_V2 */
+} __packed;
+
+#define EXTINFO_DMA_TRANS      0x0001  /* transparent DMA boundary errors */
+#define EXTINFO_GEOM_VALID     0x0002  /* geometry in c/h/s in struct valid */
+#define EXTINFO_REMOVABLE      0x0004  /* removable device */
+#define EXTINFO_WRITEVERF      0x0008  /* supports write with verify */
+#define EXTINFO_CHANGELINE     0x0010  /* changeline support */
+#define EXTINFO_LOCKABLE       0x0020  /* device is lockable */
+#define EXTINFO_MAXGEOM                0x0040  /* geometry set to max; no media */
+
+#define BIOSDISK_DEFAULT_SECSIZE       512
+
+int set_geometry(struct biosdisk_ll *, struct biosdisk_extinfo *);
+int readsects(struct biosdisk_ll *, daddr_t, int, char *, int);
diff --git a/sys/arch/i386/stand/lib/biosgetrtc.S b/sys/arch/i386/stand/lib/biosgetrtc.S
new file mode 100644 (file)
index 0000000..af1ec98
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: biosgetrtc.S,v 1.7 2011/06/16 13:27:59 joerg Exp $     */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+
+ENTRY(biosgetrtc)
+       pusha
+       pushl   %eax
+
+       xorl    %ebx, %ebx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $2, %ah
+       int     $0x1a
+       jnc     ok
+       movl    $-1, %ebx
+
+ok:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       popl    %eax
+       movb    %ch, (%eax)
+       movb    %cl, 1(%eax)
+       movb    %dh, 2(%eax)
+       movb    $0,  3(%eax)
+
+       movl    %ebx, 28(%esp)
+
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/biosgetsystime.S b/sys/arch/i386/stand/lib/biosgetsystime.S
new file mode 100644 (file)
index 0000000..984cb0c
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $NetBSD: biosgetsystime.S,v 1.3 2011/06/16 13:27:59 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/* Return system time (~18.2Hz ticks since midnight) */
+
+ENTRY(biosgetsystime)
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0, %ah
+       int     $0x1a
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       mov     %ecx, %eax
+       shl     $16, %eax
+       movw    %dx, %ax
+       movl    %eax, 28(%esp)
+
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/biosmca.S b/sys/arch/i386/stand/lib/biosmca.S
new file mode 100644 (file)
index 0000000..80be1c8
--- /dev/null
@@ -0,0 +1,117 @@
+/*     $NetBSD: biosmca.S,v 1.4 2003/02/01 14:48:18 dsl Exp $  */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992 
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/* extracted from netbsd:sys/arch/i386/stand/bios_disk.S */
+
+#include <machine/asm.h>
+
+       .data
+       .globl _C_LABEL(biosmca_ps2model)
+_C_LABEL(biosmca_ps2model):    .long 0
+
+       .text
+/*
+# BIOS call "INT 0x15 Function 0xc0" to read extended sys config info on PS/2
+#      Return:         no return value
+#
+# This function initializes biosmca_ps2model with model number as
+# identified by BIOS, if the machine is a PS/2 box (i.e. has MCA bus
+# instead of ISA).
+*/
+ENTRY(biosmca)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       push    %ecx
+       push    %edx
+       push    %esi
+       push    %edi
+       push    %eax
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       # zero %ecx
+       xorl    %ecx, %ecx
+
+       xor     %ax, %ax
+       movb    $0xc0, %ah              # subfunction
+       int     $0x15
+       jc      back
+
+       # check feature byte 1 if MCA bus present and replaces ISA
+       movb    %es:5(%bx), %al
+       andb    $0x02, %al      # bit 1 set means MCA instead of ISA
+                               # see also arch/i386/mca/mca_machdep.c
+       jnz     back
+       
+       # save model and submodel bytes to %cx
+       movb    %es:2(%bx), %ch         # model (1 byte)
+       movb    %es:3(%bx), %cl         # submodel (1 byte)
+
+back:
+       calll   _C_LABEL(real_to_prot)  # back to protected mode
+       .code32
+
+       # save model
+       movl    %ecx, _C_LABEL(biosmca_ps2model)
+
+       pop     %eax
+       pop     %edi
+       pop     %esi
+       pop     %edx
+       pop     %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/biosmca.h b/sys/arch/i386/stand/lib/biosmca.h
new file mode 100644 (file)
index 0000000..d33ade2
--- /dev/null
@@ -0,0 +1,31 @@
+/*     $NetBSD: biosmca.h,v 1.3 2008/12/14 17:03:43 christos Exp $     */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void biosmca(void);
+
+extern int biosmca_ps2model;
diff --git a/sys/arch/i386/stand/lib/biosmem.S b/sys/arch/i386/stand/lib/biosmem.S
new file mode 100644 (file)
index 0000000..4f39622
--- /dev/null
@@ -0,0 +1,78 @@
+/*     $NetBSD: biosmem.S,v 1.9 2011/06/16 13:27:59 joerg Exp $        */
+
+/*
+ * Copyright (c) 1996
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/* get mem below 1M, in kByte */
+
+ENTRY(getbasemem)
+       pusha
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       int     $0x12
+       # zero-extend 16-bit result to 32 bits.
+       movzwl  %ax, %eax
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %eax, 28(%esp)
+       popa
+       ret
+
+/* get mem above 1M, in kByte */
+
+ENTRY(getextmem1)
+       pusha
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movb    $0x88,%ah
+       int     $0x15
+
+       # zero-extend 16-bit result to 32 bits.
+       movzwl  %ax, %eax
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %eax, 28(%esp)
+       popa
+       ret
+
diff --git a/sys/arch/i386/stand/lib/biosmemps2.S b/sys/arch/i386/stand/lib/biosmemps2.S
new file mode 100644 (file)
index 0000000..0b28011
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: biosmemps2.S,v 1.6 2011/06/16 13:27:59 joerg Exp $     */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/* int getextmemp2(void buffer)
+   call int 15 function 0xc7 - later PS/2s - RETURN MEMORY-MAP INFORMATION
+   return: 0=OK, nonzero=error
+   buffer: filled with memory-map table structure
+*/
+ENTRY(getextmemps2)
+       .code32
+       movl    %eax, %edx
+       xorl    %eax, %eax
+       pusha
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       # do int15, function 0xc0 call to discover if C7h is supported
+       movb    $0xc0, %ah
+       int     $0x15
+       setc    %cl
+       jc      out             # 0xc0 not supported if carry set
+
+       # check feature byte 2, bit 4 to see if return memory map is supported
+       movb    %es:6(%bx), %al
+       andb    $0x10, %al
+       jnz     getmem          # 0xc7 supported
+       
+       # set %cl to indicate failure, and exit
+       movb    $2, %cl
+       jmp     out
+
+getmem:
+       # move the parameter to right register
+       push    %ds
+       movl    %edx, %esi
+       andl    $0xf, %esi
+       shrl    $4, %edx
+       mov     %ds, %ax
+       add     %dx, %ax
+       mov     %ax, %ds
+
+       # actually call int15, function 0xc7 now
+       movb    $0xc7, %ah
+       int     $0x15
+       setc    %cl             # save carry
+       pop     %ds
+
+out:
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movb    %cl, 28(%esp)
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/biosmemx.S b/sys/arch/i386/stand/lib/biosmemx.S
new file mode 100644 (file)
index 0000000..041451b
--- /dev/null
@@ -0,0 +1,167 @@
+/*     $NetBSD: biosmemx.S,v 1.9 2008/10/14 14:18:11 ad Exp $  */
+
+/*
+ * Copyright (c) 1997, 1999
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/* int getextmem2(int buffer[2])
+   return: 0=OK, -1=error
+   buffer[0]: extmem kBytes below 16M (max 15M/1024)
+   buffer[1]: extmem above 16M, in 64k units
+*/
+ENTRY(getextmem2)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       xorl    %ebx, %ebx
+       movl    $0xe801, %eax
+       int     $0x15
+       pushf
+
+       movw    %si, %ax
+       orw     %si, %bx
+       jz      1f              /* if zero use configured values */
+       movw    %cx, %ax        /* k below 16M (max 0x3c00 = 15MB) */
+       movw    %dx, %bx        /* 64k above 16M */
+1:
+       popf
+       setc    %bl
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    8(%ebp), %edi
+       xorl    %eax, %eax
+       movw    %cx, %ax
+       stosl
+       movw    %dx, %ax
+       stosl
+       movb    %bl, %al
+       cbw
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/* int getmementry(int *iterator, buffer[5])
+   return: 0=ok, else error
+   buffer[0]: start of memory chunk
+   buffer[2]: length (bytes)
+   buffer[4]: type
+*/
+ENTRY(getmementry)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %eax
+       movl    0(%eax), %ebx           /* index */
+       movl    $20, %ecx               /* Buffer size */
+       movl    $0x534d4150, %edx       /* "SMAP" */
+       movl    12(%ebp), %edi          /* buffer address */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di               /* buffer addres now in ES:DI */
+
+       movl    $0xe820, %eax           /* Some BIOS check EAX value */
+       int     $0x15
+
+       setc    %cl
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    8(%ebp), %eax
+       movl    %ebx, 0(%eax)           /* updated index */
+       xorl    %eax, %eax
+       movb    %cl, %al
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/* int biosA20(void)
+   return: 0=ok, else error
+*/
+ENTRY(biosA20)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movl    $0x2401, %eax
+       int     $0x15
+       setc    %cl
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movzbl  %cl, %eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/biospci.c b/sys/arch/i386/stand/lib/biospci.c
new file mode 100644 (file)
index 0000000..d40eddd
--- /dev/null
@@ -0,0 +1,96 @@
+/*     $NetBSD: biospci.c,v 1.5 2008/12/14 17:03:43 christos Exp $      */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * basic PCI functions for libsa needs lowlevel parts from bios_pci.S
+ */
+
+#include <lib/libsa/stand.h>
+
+#include "pcivar.h"
+
+extern int pcibios_present(int *);
+extern int pcibios_finddev(int, int, int, unsigned int *);
+extern int pcibios_cfgread(unsigned int, int, int *);
+extern int pcibios_cfgwrite(unsigned int, int, int);
+
+#define PCISIG ('P' | ('C' << 8) | ('I' << 16) | (' ' << 24))
+
+int
+pcicheck(void)
+{
+       int             ret, sig;
+
+       ret = pcibios_present(&sig);
+
+       if ((ret & 0xff00) || (sig != PCISIG))
+               return -1;
+
+       return 0;
+}
+
+int
+pcifinddev(int vid, int did, pcihdl_t *handle)
+{
+       int             ret;
+
+       *handle = 0;
+
+       ret = pcibios_finddev(vid, did, 0, handle);
+
+       if (ret)
+               return -1;
+
+       return 0;
+}
+
+int
+pcicfgread(pcihdl_t *handle, int off, int *val)
+{
+       int             ret;
+
+       ret = pcibios_cfgread(*handle, off, val);
+
+       if (ret)
+               return -1;
+
+       return 0;
+}
+
+int
+pcicfgwrite(pcihdl_t *handle, int off, int val)
+{
+       int             ret;
+
+       ret = pcibios_cfgwrite(*handle, off, val);
+
+       if (ret)
+               return -1;
+
+       return 0;
+}
diff --git a/sys/arch/i386/stand/lib/biosreboot.S b/sys/arch/i386/stand/lib/biosreboot.S
new file mode 100644 (file)
index 0000000..315b720
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: biosreboot.S,v 1.5 2011/06/16 13:27:59 joerg Exp $     */
+
+/*
+ * Copyright (c) 1997
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <machine/asm.h>
+
+       .text
+
+/* Call INT 19 to do the equivalent of CTL-ALT-DEL */
+
+ENTRY(reboot)
+       pusha
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       int     $0x19
+
+       /* NOTE: We should never even get past this point. */
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %ebx, 28(%esp)
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/biosvbe.S b/sys/arch/i386/stand/lib/biosvbe.S
new file mode 100644 (file)
index 0000000..92de9cb
--- /dev/null
@@ -0,0 +1,358 @@
+/* $NetBSD: biosvbe.S,v 1.3 2011/02/20 22:03:13 jakllsch Exp $ */
+
+/*-
+ * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/*
+ * VESA BIOS Extensions routines
+ */
+
+/*
+ * Function 00h - Return VBE Controller Information
+ *
+ * int biosvbe_info(struct vbeinfoblock *)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_info)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %edi   /* vbe info block address*/
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %es
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di       /* mode info block address now in es:di */
+
+       movw    $0x4f00, %ax    /* get vbe info block */
+       int     $0x10
+
+       pop     %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 01h - Return VBE Mode Information
+ *
+ * int biosvbe_get_mode_info(int mode, struct modeinfoblock *mi)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_get_mode_info)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %ecx   /* mode number */
+       movl    12(%ebp), %edi  /* mode info block address */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %es
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di       /* mode info block address now in es:di */
+
+       movw    $0x4f01, %ax    /* get mode info block */
+       int     $0x10
+
+       pop     %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 02h - Set VBE Mode
+ *
+ * int biosvbe_set_mode(int mode)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_set_mode)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %ebx   /* mode number */
+       orl     $0x4000, %ebx
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movw    $0x4f02, %ax    /* set mode */
+       int     $0x10
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 08h - Set/Get DAC Palette Format
+ *
+ * int biosvbe_palette_format(int format)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_palette_format)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %ebx   /* mode number */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movw    $0x4f08, %ax    /* get/set palette format */
+       int     $0x10
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 09h - Set/Get Palette Data
+ *
+ * int biosvbe_palette_data(int mode, int reg, struct paletteentry *)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_palette_data)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %ebx   /* mode number */
+       movl    12(%ebp), %edx  /* register */
+       movl    16(%ebp), %edi  /* palette entry address */
+       movl    $1, %ecx        /* # palette entries to update */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %es
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di       /* palette entry address now in es:di */
+
+       movw    $0x4f09, %ax    /* get/set palette entry */
+       int     $0x10
+
+       pop     %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 15h BL=00h - Report VBE/DDC Capabilities
+ *
+ * int biosvbe_ddc_caps(void)
+ * return: VBE/DDC capabilities
+ */
+ENTRY(biosvbe_ddc_caps)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       pushw   %es
+
+       xorw    %di, %di
+       movw    %di, %es        /* es:di == 0:0 */
+
+       movw    $0x4f15, %ax    /* display identification extensions */
+       mov     $0x00, %bx      /* report DDC capabilities */
+       mov     $0x00, %cx      /* controller unit number (00h = primary) */
+       int     $0x10
+
+       popw    %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %eax,%ecx
+       movl    $0x0000,%eax
+       andl    $0xffff,%ecx
+       cmpl    $0x004f,%ecx
+       jne     1f
+       andl    $0xffff,%ebx
+       movl    %ebx,%eax
+1:
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * Function 15h BL=01h - Read EDID
+ *
+ * int biosvbe_ddc_read_edid(int blockno, void *buf)
+ * return: VBE call status
+ */
+ENTRY(biosvbe_ddc_read_edid)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %edx   /* EDID block number */
+       movl    12(%ebp), %edi  /* EDID block address */
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       push    %es
+
+       push    %di
+       shrl    $4, %edi
+       mov     %ds, %ax
+       add     %di, %ax
+       mov     %ax, %es
+       pop     %di
+       and     $0xf, %di       /* EDID block address now in es:di */
+
+       movw    $0x4f15, %ax    /* display identification extensions */
+       mov     $0x01, %bx      /* read EDID */
+       mov     $0x00, %cx      /* controller unit number (00h = primary) */
+       int     $0x10
+
+       pop     %es
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       andl    $0xffff,%eax
+
+       pop     %edi
+       pop     %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
diff --git a/sys/arch/i386/stand/lib/biosvideomode.S b/sys/arch/i386/stand/lib/biosvideomode.S
new file mode 100644 (file)
index 0000000..c3b0df8
--- /dev/null
@@ -0,0 +1,65 @@
+/*     $NetBSD: biosvideomode.S,v 1.3 2003/04/16 13:49:21 dsl Exp $    */
+
+/*
+ * Copyright (c) 1996
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+ENTRY(biosvideomode)
+       pushl   %ebp
+       movl    %esp,%ebp
+       pushl   %ebx
+       push    %esi
+       push    %edi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movb    $0, %ah
+       movb    $2, %al
+       int     $0x10
+       # zero-extend 16-bit result to 32 bits.
+       movl    $0, %ebx
+       movw    %ax,%bx
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       movl    %ebx, %eax
+
+       pop     %edi
+       pop     %esi
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/boot_params.S b/sys/arch/i386/stand/lib/boot_params.S
new file mode 100644 (file)
index 0000000..5309aff
--- /dev/null
@@ -0,0 +1,15 @@
+/*     $NetBSD: boot_params.S,v 1.6 2010/01/17 14:54:44 drochner Exp $ */
+
+/* Default boot parameters - must match struct x86_boot_params in bootblock.h */
+
+#ifdef BOOTPARAM_DEFFLAGS
+       .long   BOOTPARAM_DEFFLAGS
+#else
+       .long   0x0
+#endif
+       .long   5                       /* timeout in seconds */
+       .long   0                       /* console device 0 => CONSDEV_PC */
+       .long   9600                    /* serial baud rate */
+       .space  16                      /* md5 boot password */
+       .space  64                      /* keyboard xlat map */
+       .long   0                       /* console ioaddr */
diff --git a/sys/arch/i386/stand/lib/bootinfo.c b/sys/arch/i386/stand/lib/bootinfo.c
new file mode 100644 (file)
index 0000000..84032e0
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: bootinfo.c,v 1.5 2008/12/14 18:46:33 christos Exp $    */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include "libi386.h"
+#include "bootinfo.h"
+
+struct bootinfo *bootinfo;
+
+void
+bi_add(struct btinfo_common *what, int type, int size)
+{
+       what->len = size;
+       what->type = type;
+
+       if (bootinfo)
+               bootinfo->entry[bootinfo->nentries++] = vtophys(what);
+}
diff --git a/sys/arch/i386/stand/lib/bootinfo.h b/sys/arch/i386/stand/lib/bootinfo.h
new file mode 100644 (file)
index 0000000..df1d5aa
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: bootinfo.h,v 1.9 2006/01/25 18:28:26 christos Exp $    */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/bootinfo.h>
+
+struct bootinfo {
+       int nentries;
+       physaddr_t entry[1];
+};
+
+extern struct bootinfo *bootinfo;
+
+#define BI_ALLOC(max) (bootinfo = alloc(sizeof(struct bootinfo) \
+                                        + ((max) - 1) * sizeof(physaddr_t))) \
+                      ->nentries = 0
+
+#define BI_FREE() dealloc(bootinfo, 0)
+
+#define BI_ADD(x, type, size) bi_add((struct btinfo_common *)(x), type, size)
+
+void bi_add(struct btinfo_common *, int, int);
+void bi_getbiosgeom(void);
+void bi_getmemmap(void);
diff --git a/sys/arch/i386/stand/lib/bootinfo_biosgeom.c b/sys/arch/i386/stand/lib/bootinfo_biosgeom.c
new file mode 100644 (file)
index 0000000..43e8784
--- /dev/null
@@ -0,0 +1,181 @@
+/*     $NetBSD: bootinfo_biosgeom.c,v 1.21 2010/12/25 01:19:33 jakllsch Exp $  */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <machine/disklabel.h>
+#include <machine/cpu.h>
+
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include "libi386.h"
+#include "biosdisk_ll.h"
+#include "bootinfo.h"
+
+#ifdef BIOSDISK_EXTINFO_V3
+static struct {
+       char    *name;
+       int     flag;
+} bus_names[] = { {"ISA", BI_GEOM_BUS_ISA},
+                 {"PCI", BI_GEOM_BUS_PCI},
+                 {NULL, BI_GEOM_BUS_OTHER} };
+static struct {
+       char    *name;
+       int     flag;
+} iface_names[] = { {"ATA", BI_GEOM_IFACE_ATA},
+                   {"ATAPI", BI_GEOM_IFACE_ATAPI},
+                   {"SCSI", BI_GEOM_IFACE_SCSI},
+                   {"USB", BI_GEOM_IFACE_USB},
+                   {"1394", BI_GEOM_IFACE_1394},
+                   {"FIBRE", BI_GEOM_IFACE_FIBRE},
+                   {NULL, BI_GEOM_IFACE_OTHER} };
+#endif
+
+void
+bi_getbiosgeom(void)
+{
+       struct btinfo_biosgeom *bibg;
+       int i, j, nvalid;
+       int nhd;
+       unsigned int cksum;
+       struct biosdisk_ll d;
+       struct biosdisk_extinfo ed;
+       char buf[BIOSDISK_DEFAULT_SECSIZE];
+
+       nhd = get_harddrives();
+#ifdef GEOM_DEBUG
+       printf("nhd %d\n", nhd);
+#endif
+
+       bibg = alloc(sizeof(struct btinfo_biosgeom)
+                    + (nhd - 1) * sizeof(struct bi_biosgeom_entry));
+       if (bibg == NULL)
+               return;
+
+       for (i = nvalid = 0; i < MAX_BIOSDISKS && nvalid < nhd; i++) {
+
+               d.dev = 0x80 + i;
+
+               if (set_geometry(&d, &ed))
+                       continue;
+               memset(&bibg->disk[nvalid], 0, sizeof(bibg->disk[nvalid]));
+
+               bibg->disk[nvalid].sec = d.sec;
+               bibg->disk[nvalid].head = d.head;
+               bibg->disk[nvalid].cyl = d.cyl;
+               bibg->disk[nvalid].dev = d.dev;
+
+               if (readsects(&d, 0, 1, buf, 0)) {
+                       bibg->disk[nvalid].flags |= BI_GEOM_INVALID;
+                       nvalid++;
+                       continue;
+               }
+
+#ifdef GEOM_DEBUG
+               printf("#%d: %x: C %d H %d S %d\n", nvalid,
+                      d.dev, d.cyl, d.head, d.sec);
+               printf("   sz %d fl %x cyl %d head %d sec %d totsec %"PRId64" sbytes %d\n",
+                      ed.size, ed.flags, ed.cyl, ed.head, ed.sec,
+                      ed.totsec, ed.sbytes);
+#endif
+
+               if (d.flags & BIOSDISK_INT13EXT) {
+                       bibg->disk[nvalid].totsec = ed.totsec;
+                       bibg->disk[nvalid].flags |= BI_GEOM_EXTINT13;
+               }
+#ifdef BIOSDISK_EXTINFO_V3
+#ifdef GEOM_DEBUG
+               printf("   edd_cfg %x, sig %x, len %x, bus %s type %s\n",
+                      ed.edd_cfg, ed.devpath_sig, ed.devpath_len,
+                      ed.host_bus, ed.iface_type);
+#endif
+
+               /* The v3.0 stuff will help identify the disks */
+               if (ed.size >= offsetof(struct biosdisk_ext13info, checksum)
+                   && ed.devpath_sig == EXTINFO_DEVPATH_SIGNATURE) {
+                       char *cp;
+
+                       for (cp = (void *)&ed.devpath_sig, cksum = 0;
+                            cp <= (char *)&ed.checksum; cp++) {
+                               cksum += *cp;
+                       }
+                       if ((cksum & 0xff) != 0)
+                               bibg->disk[nvalid].flags |= BI_GEOM_BADCKSUM;
+#ifdef GEOM_DEBUG
+                       printf("checksum %x\n", cksum & 0xff);
+#endif
+                       for (j = 0; ; j++) {
+                               cp = bus_names[j].name;
+                               if (cp == NULL)
+                                       break;
+                               if (strncmp(cp, ed.host_bus,
+                                           sizeof(ed.host_bus)) == 0)
+                                       break;
+                       }
+#ifdef GEOM_DEBUG
+                       printf("bus %s (%x)\n", cp ? cp : "null",
+                              bus_names[j].flag);
+#endif
+                       bibg->disk[nvalid].flags |= bus_names[j].flag;
+                       for (j = 0; ; j++) {
+                               cp = iface_names[j].name;
+                               if (cp == NULL)
+                                       break;
+                               if (strncmp(cp, ed.iface_type,
+                                           sizeof(ed.iface_type)) == 0)
+                                       break;
+                       }
+                       bibg->disk[nvalid].flags |= iface_names[j].flag;
+                       /* Dump raw interface path and device path */
+                       bibg->disk[nvalid].interface_path =
+                                       ed.interface_path.ip_32[0];
+                       bibg->disk[nvalid].device_path =
+                                       ed.device_path.dp_64[0];
+#ifdef GEOM_DEBUG
+                       printf("device %s (%x) interface %x path %llx\n",
+                              cp ? cp : "null",
+                              iface_names[j].flag,
+                              ed.interface_path.ip_32[0],
+                              ed.device_path.dp_64[0]);
+#endif
+               }
+#endif
+
+               for (j = 0, cksum = 0; j < BIOSDISK_DEFAULT_SECSIZE; j++)
+                       cksum += buf[j];
+               bibg->disk[nvalid].cksum = cksum;
+               memcpy(bibg->disk[nvalid].dosparts, &buf[MBR_PART_OFFSET],
+                      sizeof(bibg->disk[nvalid].dosparts));
+               nvalid++;
+       }
+
+       bibg->num = nvalid;
+
+       BI_ADD(bibg, BTINFO_BIOSGEOM, sizeof(struct btinfo_biosgeom)
+              + nvalid * sizeof(struct bi_biosgeom_entry));
+}
diff --git a/sys/arch/i386/stand/lib/bootinfo_memmap.c b/sys/arch/i386/stand/lib/bootinfo_memmap.c
new file mode 100644 (file)
index 0000000..ee69c52
--- /dev/null
@@ -0,0 +1,61 @@
+/*     $NetBSD: bootinfo_memmap.c,v 1.5 2008/12/14 17:03:43 christos Exp $     */
+
+/*
+ * Copyright (c) 1999
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <lib/libsa/stand.h>
+#include "libi386.h"
+#include "bootinfo.h"
+
+extern int getmementry(int *, int *);
+
+void
+bi_getmemmap(void)
+{
+       int buf[5], i, nranges, n;
+       struct btinfo_memmap *bimm;
+
+       nranges = 0;
+       i = 0;
+       do {
+               if (getmementry(&i, buf))
+                       break;
+               nranges++;
+       } while (i);
+
+       bimm = alloc(sizeof(struct btinfo_memmap)
+               + (nranges - 1) * sizeof(struct bi_memmap_entry));
+
+       i = 0;
+       for (n = 0; n < nranges; n++) {
+               getmementry(&i, buf);
+               memcpy(&bimm->entry[n], buf, sizeof(struct bi_memmap_entry));
+       }
+       bimm->num = nranges;
+
+       BI_ADD(bimm, BTINFO_MEMMAP, sizeof(struct btinfo_memmap)
+              + (nranges - 1) * sizeof(struct bi_memmap_entry));
+}
diff --git a/sys/arch/i386/stand/lib/bootmenu.c b/sys/arch/i386/stand/lib/bootmenu.c
new file mode 100644 (file)
index 0000000..038d126
--- /dev/null
@@ -0,0 +1,386 @@
+/*     $NetBSD: bootmenu.c,v 1.10 2011/08/18 13:20:04 christos Exp $   */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SMALL
+
+#include <sys/types.h>
+#include <sys/reboot.h>
+#include <sys/bootblock.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/ufs.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <bootmenu.h>
+
+#define isnum(c) ((c) >= '0' && (c) <= '9')
+
+extern struct x86_boot_params boot_params;
+extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
+
+#define MENUFORMAT_AUTO          0
+#define MENUFORMAT_NUMBER 1
+#define MENUFORMAT_LETTER 2
+
+struct bootconf_def bootconf;
+
+int
+atoi(const char *in)
+{
+       char *c;
+       int ret;
+
+       ret = 0;
+       c = (char *)in;
+       if (*c == '-')
+               c++;
+       for (; isnum(*c); c++)
+               ret = (ret * 10) + (*c - '0');
+
+       return (*in == '-') ? -ret : ret;
+}
+
+/*
+ * This function parses a boot.cfg file in the root of the filesystem
+ * (if present) and populates the global boot configuration.
+ *
+ * The file consists of a number of lines each terminated by \n
+ * The lines are in the format keyword=value. There should not be spaces
+ * around the = sign.
+ *
+ * The recognised keywords are:
+ * banner: text displayed instead of the normal welcome text
+ * menu: Descriptive text:command to use
+ * timeout: Timeout in seconds (overrides that set by installboot)
+ * default: the default menu option to use if Return is pressed
+ * consdev: the console device to use
+ * format: how menu choices are displayed: (a)utomatic, (n)umbers or (l)etters
+ * clear: whether to clear the screen or not
+ *
+ * Example boot.cfg file:
+ * banner=Welcome to NetBSD
+ * banner=Please choose the boot type from the following menu
+ * menu=Boot NetBSD:boot netbsd
+ * menu=Boot into single user mode:boot netbsd -s
+ * menu=:boot hd1a:netbsd -cs
+ * menu=Goto boot comand line:prompt
+ * timeout=10
+ * consdev=com0
+ * default=1
+*/
+void
+parsebootconf(const char *conf)
+{
+       char *bc, *c;
+       int cmenu, cbanner, len;
+       int fd, err, off;
+       struct stat st;
+       char *next, *key, *value, *v2;
+
+       /* Clear bootconf structure */
+       memset((void *)&bootconf, 0, sizeof(bootconf));
+
+       /* Set timeout to configured */
+       bootconf.timeout = boot_params.bp_timeout;
+
+       /* automatically switch between letter and numbers on menu */
+       bootconf.menuformat = MENUFORMAT_AUTO;
+
+       fd = open(BOOTCONF, 0);
+       if (fd < 0)
+               return;
+
+       err = fstat(fd, &st);
+       if (err == -1) {
+               close(fd);
+               return;
+       }
+
+       /*
+        * Check the size. A bootconf file is normally only a few
+        * hundred bytes long. If it is much bigger than expected,
+        * don't try to load it. We can't load something big into
+        * an 8086 real mode segment anyway, and in pxeboot this is
+        * probably a case of the loader getting a filename for the
+        * kernel and thinking it is boot.cfg by accident. (The 32k
+        * number is arbitrary but 8086 real mode data segments max
+        * out at 64k.)
+        */
+       if (st.st_size > 32768) {
+               close(fd);
+               return;
+       }
+
+       bc = alloc(st.st_size + 1);
+       if (bc == NULL) {
+               printf("Could not allocate memory for boot configuration\n");
+               return;
+       }
+
+       off = 0;
+       do {
+               len = read(fd, bc + off, 1024);
+               if (len <= 0)
+                       break;
+               off += len;
+       } while (len > 0);
+       bc[off] = '\0';
+
+       close(fd);
+       /* bc now contains the whole boot.cfg file */
+
+       cmenu = 0;
+       cbanner = 0;
+       for (c = bc; *c; c = next) {
+               key = c;
+               /* find end of line */
+               for (; *c && *c != '\n'; c++)
+                       /* zero terminate line on start of comment */
+                       if (*c == '#')
+                               *c = 0;
+               /* zero terminate line */
+               if (*(next = c))
+                       *next++ = 0;
+               /* Look for = separator between key and value */
+               for (c = key; *c && *c != '='; c++)
+                       continue;
+               /* Ignore lines with no key=value pair */
+               if (*c == '\0')
+                       continue;
+
+               /* zero terminate key which points to keyword */
+               *c++ = 0;
+               value = c;
+               /* Look for end of line (or file) and zero terminate value */
+               for (; *c && *c != '\n'; c++)
+                       continue;
+               *c = 0;
+
+               if (!strncmp(key, "menu", 4)) {
+                       /*
+                        * Parse "menu=<description>:<command>".  If the
+                        * description is empty ("menu=:<command>)",
+                        * then re-use the command as the description.
+                        * Note that the command may contain embedded
+                        * colons.
+                        */
+                       if (cmenu >= MAXMENU)
+                               continue;
+                       bootconf.desc[cmenu] = value;
+                       for (v2 = value; *v2 && *v2 != ':'; v2++)
+                               continue;
+                       if (*v2) {
+                               *v2++ = 0;
+                               bootconf.command[cmenu] = v2;
+                               if (! *value)
+                                       bootconf.desc[cmenu] = v2;
+                               cmenu++;
+                       } else {
+                               /* No delimiter means invalid line */
+                               bootconf.desc[cmenu] = NULL;
+                       }
+               } else if (!strncmp(key, "banner", 6)) {
+                       if (cbanner < MAXBANNER)
+                               bootconf.banner[cbanner++] = value;
+               } else if (!strncmp(key, "timeout", 7)) {
+                       if (!isnum(*value))
+                               bootconf.timeout = -1;
+                       else
+                               bootconf.timeout = atoi(value);
+               } else if (!strncmp(key, "default", 7)) {
+                       bootconf.def = atoi(value) - 1;
+               } else if (!strncmp(key, "consdev", 7)) {
+                       bootconf.consdev = value;
+               } else if (!strncmp(key, "load", 4)) {
+                       module_add(value);
+               } else if (!strncmp(key, "format", 6)) {
+                       printf("value:%c\n", *value);
+                       switch (*value) {
+                       case 'a':
+                       case 'A':
+                               bootconf.menuformat = MENUFORMAT_AUTO;
+                               break;
+
+                       case 'n':
+                       case 'N':
+                       case 'd':
+                       case 'D':
+                               bootconf.menuformat = MENUFORMAT_NUMBER;
+                               break;
+
+                       case 'l':
+                       case 'L':
+                               bootconf.menuformat = MENUFORMAT_LETTER;
+                               break;
+                       }
+               } else if (!strncmp(key, "clear", 5)) {
+                       bootconf.clear = !!atoi(value);
+               } else if (!strncmp(key, "userconf", 8)) {
+                       userconf_add(value);
+               }
+       }
+       switch (bootconf.menuformat) {
+       case MENUFORMAT_AUTO:
+               if (cmenu > 9 && bootconf.timeout > 0)
+                       bootconf.menuformat = MENUFORMAT_LETTER;
+               else
+                       bootconf.menuformat = MENUFORMAT_NUMBER;
+               break;
+
+       case MENUFORMAT_NUMBER:
+               if (cmenu > 9 && bootconf.timeout > 0)
+                       cmenu = 9;
+               break;
+       }
+
+       bootconf.nummenu = cmenu;
+       if (bootconf.def < 0)
+               bootconf.def = 0;
+       if (bootconf.def >= cmenu)
+               bootconf.def = cmenu - 1;
+}
+
+/*
+ * doboottypemenu will render the menu and parse any user input
+ */
+static int
+getchoicefrominput(char *input, int def)
+{
+       int choice, usedef;
+
+       choice = -1;
+       usedef = 0;
+
+       if (*input == '\0' || *input == '\r' || *input == '\n') {
+               choice = def;
+               usedef = 1;
+       } else if (*input >= 'A' && *input < bootconf.nummenu + 'A')
+               choice = (*input) - 'A';
+       else if (*input >= 'a' && *input < bootconf.nummenu + 'a')
+               choice = (*input) - 'a';
+       else if (isnum(*input)) {
+               choice = atoi(input) - 1;
+               if (choice < 0 || choice >= bootconf.nummenu)
+                       choice = -1;
+       }
+
+       if (bootconf.menuformat != MENUFORMAT_LETTER &&
+           !isnum(*input) && !usedef)
+               choice = -1;
+
+       return choice;
+}
+
+void
+doboottypemenu(void)
+{
+       int choice;
+       char input[80], *ic, *oc;
+
+       printf("\n");
+       /* Display menu */
+       if (bootconf.menuformat == MENUFORMAT_LETTER) {
+               for (choice = 0; choice < bootconf.nummenu; choice++)
+                       printf("    %c. %s\n", choice + 'A',
+                           bootconf.desc[choice]);
+       } else {
+               /* Can't use %2d format string with libsa */
+               for (choice = 0; choice < bootconf.nummenu; choice++)
+                       printf("    %s%d. %s\n",
+                           (choice < 9) ?  " " : "",
+                           choice + 1,
+                           bootconf.desc[choice]);
+       }
+       choice = -1;
+       for (;;) {
+               input[0] = '\0';
+
+               if (bootconf.timeout < 0) {
+                       if (bootconf.menuformat == MENUFORMAT_LETTER)
+                               printf("\nOption: [%c]:",
+                                   bootconf.def + 'A');
+                       else
+                               printf("\nOption: [%d]:",
+                                   bootconf.def + 1);
+
+                       gets(input);
+                       choice = getchoicefrominput(input, bootconf.def);
+               } else if (bootconf.timeout == 0)
+                       choice = bootconf.def;
+               else  {
+                       printf("\nChoose an option; RETURN for default; "
+                              "SPACE to stop countdown.\n");
+                       if (bootconf.menuformat == MENUFORMAT_LETTER)
+                               printf("Option %c will be chosen in ",
+                                   bootconf.def + 'A');
+                       else
+                               printf("Option %d will be chosen in ",
+                                   bootconf.def + 1);
+                       input[0] = awaitkey(bootconf.timeout, 1);
+                       input[1] = '\0';
+                       choice = getchoicefrominput(input, bootconf.def);
+                       /* If invalid key pressed, drop to menu */
+                       if (choice == -1)
+                               bootconf.timeout = -1;
+               }
+               if (choice < 0)
+                       continue;
+               if (!strcmp(bootconf.command[choice], "prompt") &&
+                   ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 ||
+                   check_password((char *)boot_params.bp_password))) {
+                       printf("type \"?\" or \"help\" for help.\n");
+                       bootmenu(); /* does not return */
+               } else {
+                       ic = bootconf.command[choice];
+                       /* Split command string at ; into separate commands */
+                       do {
+                               oc = input;
+                               /* Look for ; separator */
+                               for (; *ic && *ic != COMMAND_SEPARATOR; ic++)
+                                       *oc++ = *ic;
+                               if (*input == '\0')
+                                       continue;
+                               /* Strip out any trailing spaces */
+                               oc--;
+                               for (; *oc == ' ' && oc > input; oc--);
+                               *++oc = '\0';
+                               if (*ic == COMMAND_SEPARATOR)
+                                       ic++;
+                               /* Stop silly command strings like ;;; */
+                               if (*input != '\0')
+                                       docommand(input);
+                               /* Skip leading spaces */
+                               for (; *ic == ' '; ic++);
+                       } while (*ic);
+               }
+
+       }
+}
+
+#endif /* !SMALL */
diff --git a/sys/arch/i386/stand/lib/bootmenu.h b/sys/arch/i386/stand/lib/bootmenu.h
new file mode 100644 (file)
index 0000000..0a2053d
--- /dev/null
@@ -0,0 +1,53 @@
+/*     $NetBSD: bootmenu.h,v 1.2 2008/12/13 23:30:54 christos Exp $    */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _BOOTMENU_H
+#define _BOOTMENU_H
+
+#define BOOTCONF "boot.cfg"
+#define MAXMENU 20
+#define MAXBANNER 12
+#define COMMAND_SEPARATOR ';'
+
+void parsebootconf(const char *);
+void doboottypemenu(void);
+int atoi(const char *);
+
+struct bootconf_def {
+       char *banner[MAXBANNER];        /* Banner text */
+       char *command[MAXMENU];         /* Menu commands per entry*/
+       char *consdev;                  /* Console device */
+       int def;                        /* Default menu option */
+       char *desc[MAXMENU];            /* Menu text per entry */
+       int nummenu;                    /* Number of menu items */
+       int timeout;                    /* Timeout in seconds */
+       int menuformat;                 /* Print letters instead of numbers? */
+       int clear;                      /* Clear the screen? */
+} extern bootconf;
+
+#endif /* !_BOOTMENU_H */
diff --git a/sys/arch/i386/stand/lib/bootmod.h b/sys/arch/i386/stand/lib/bootmod.h
new file mode 100644 (file)
index 0000000..6be5653
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: bootmod.h,v 1.5 2011/11/28 07:56:54 tls Exp $  */
+
+/*-
+ * Copyright (c) 2008 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _BOOTMOD_H
+#define _BOOTMOD_H
+
+typedef struct boot_module {
+       char                    *bm_path;
+       ssize_t                 bm_len;
+       uint8_t                 bm_type;
+#define        BM_TYPE_KMOD            0x00
+#define        BM_TYPE_IMAGE           0x01
+#define BM_TYPE_RND            0x02
+       struct boot_module      *bm_next;
+} boot_module_t;
+
+extern boot_module_t *boot_modules;
+extern bool boot_modules_enabled;
+
+#endif /* !_BOOTMOD_H */
diff --git a/sys/arch/i386/stand/lib/comio.S b/sys/arch/i386/stand/lib/comio.S
new file mode 100644 (file)
index 0000000..4ac9149
--- /dev/null
@@ -0,0 +1,148 @@
+/*     $NetBSD: comio.S,v 1.4 2003/04/16 14:23:11 dsl Exp $    */
+
+/* serial console handling
+  modelled after code in FreeBSD:sys/i386/boot/netboot/start2.S
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/**************************************************************************
+INIT - Initialization (com number)
+**************************************************************************/
+ENTRY(cominit)
+       push    %ebp
+       mov     %esp,%ebp
+       push    %ebx
+       push    %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp), %edx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       # Initialize the serial port (dl) to 9600 baud, 8N1.
+       movb    $0xe3, %al
+       movb    $0, %ah
+       int     $0x14
+       mov     %ax,%bx
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       xor     %eax,%eax
+       mov     %bx,%ax
+
+       pop     %edi
+       pop     %esi
+       pop     %edx
+       pop     %ebx
+       pop     %ebp
+       ret
+
+/**************************************************************************
+PUTC - Print a character (char, com number)
+**************************************************************************/
+ENTRY(computc)
+       push    %ebp
+       mov     %esp,%ebp
+       push    %ecx
+       push    %ebx
+       push    %edx
+       push    %esi
+       push    %edi
+
+       movb    8(%ebp),%cl
+       movl    12(%ebp),%edx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    %cl,%al
+       movb    $0x01, %ah
+       int     $0x14
+
+       movb    %ah,%bl
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       xor     %eax,%eax
+       movb    %bl,%al
+
+       pop     %edi
+       pop     %esi
+       pop     %edx
+       pop     %ebx
+       pop     %ecx
+       pop     %ebp
+       ret
+
+/**************************************************************************
+GETC - Get a character (com number)
+**************************************************************************/
+ENTRY(comgetc)
+       push    %ebp
+       mov     %esp,%ebp
+       push    %ebx
+       push    %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp),%edx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x02, %ah
+       int     $0x14
+       mov     %ax, %bx
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       xor     %eax,%eax
+       mov     %bx,%ax
+
+       pop     %edi
+       pop     %esi
+       pop     %edx
+       pop     %ebx
+       pop     %ebp
+       ret
+
+/**************************************************************************
+ISKEY - Check for keyboard interrupt (com number)
+**************************************************************************/
+ENTRY(comstatus)
+       push    %ebp
+       mov     %esp,%ebp
+       push    %ebx
+       push    %edx
+       push    %esi
+       push    %edi
+
+       movl    8(%ebp),%edx
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x03, %ah
+       int     $0x14
+       mov     %ax,%bx
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       xor     %eax,%eax
+       mov     %bx,%ax
+
+       pop     %edi
+       pop     %esi
+       pop     %edx
+       pop     %ebx
+       pop     %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/comio_direct.c b/sys/arch/i386/stand/lib/comio_direct.c
new file mode 100644 (file)
index 0000000..e746210
--- /dev/null
@@ -0,0 +1,243 @@
+/*     $NetBSD: comio_direct.c,v 1.10 2008/12/14 18:46:33 christos Exp $       */
+
+/*-
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     Charles M. Hannum.  All rights reserved.
+ *
+ * Taken from sys/dev/isa/com.c and integrated into standalone boot
+ * programs by Martin Husemann.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)com.c       7.5 (Berkeley) 5/16/91
+ */
+
+#include <sys/types.h>
+#include <lib/libsa/stand.h>
+#include <machine/pio.h>
+#include <dev/ic/comreg.h>
+#include "comio_direct.h"
+#include "libi386.h"
+
+/* preread buffer for xon/xoff handling */
+#define XON    0x11
+#define        XOFF    0x13
+#define        SERBUFSIZE      16
+static u_char serbuf[SERBUFSIZE];
+static int serbuf_read = 0;
+static int serbuf_write = 0;
+static int stopped = 0;
+
+#define        ISSET(t,f)      ((t) & (f))
+
+#define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
+#define RATE_9600 divrnd((COM_FREQ / 16), 9600)
+
+/*
+ * calculate divisor for a given speed
+ */
+static int
+comspeed(long speed)
+{
+       int x, err;
+
+       if (speed <= 0)
+               speed = 9600;
+       x = divrnd((COM_FREQ / 16), speed);
+       if (x <= 0)
+               return RATE_9600;
+       err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
+       if (err < 0)
+               err = -err;
+       if (err > COM_TOLERANCE)
+               return RATE_9600;
+       return x;
+}
+
+/*
+ * get a character
+ */
+int
+comgetc_d(int combase)
+{
+       u_char stat, c;
+
+       if (serbuf_read != serbuf_write) {
+               c = serbuf[serbuf_read++];
+               if (serbuf_read >= SERBUFSIZE)
+                       serbuf_read = 0;
+               return c;
+       }
+
+       for (;;) {
+               while (!ISSET(stat = inb(combase + com_lsr), LSR_RXRDY))
+                       continue;
+               c = inb(combase + com_data);
+               inb(combase + com_iir);
+               if (c != XOFF) {
+                       stopped = 0;
+                       break;  /* got a real char, deliver it... */
+               }
+               stopped = 1;
+       }
+       return c;
+}
+
+/*
+ * output a character, return nonzero on success
+ */
+int
+computc_d(int c, int combase)
+{
+       u_char stat;
+       int timo;
+
+       /* check for old XOFF */
+       while (stopped)
+               comgetc_d(combase);     /* wait for XON */
+
+       /* check for new XOFF */
+       if (comstatus_d(combase)) {
+               int c = comgetc_d(combase);     /* XOFF handled in comgetc_d */
+               /* stuff char into preread buffer */
+               serbuf[serbuf_write++] = c;
+               if (serbuf_write >= SERBUFSIZE)
+                       serbuf_write = 0;
+       }
+
+       /* wait for any pending transmission to finish */
+       timo = 50000;
+       while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY)
+           && --timo)
+               continue;
+       if (timo == 0) return 0;
+       outb(combase + com_data, c);
+       /* wait for this transmission to complete */
+       timo = 1500000;
+       while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY)
+           && --timo)
+               continue;
+       if (timo == 0) return 0;
+       /* clear any interrupts generated by this transmission */
+       inb(combase + com_iir);
+
+       return 1;
+}
+
+/*
+ * Initialize UART to known state.
+ */
+int
+cominit_d(int combase, int speed)
+{
+       int rate, err;
+
+       serbuf_read = 0;
+       serbuf_write = 0;
+
+       outb(combase + com_cfcr, LCR_DLAB);
+       if (speed == 0) {
+               /* Try to determine the current baud rate */
+               rate = inb(combase + com_dlbl) | inb(combase + com_dlbh) << 8;
+               if (rate == 0)
+                       rate = RATE_9600;
+               speed = divrnd((COM_FREQ / 16), rate);
+               err = speed - (speed + 150)/300 * 300;
+               speed -= err;
+               if (err < 0)
+                       err = -err;
+               if (err > 50)
+                       speed = 9600;
+       }
+       rate = comspeed(speed);
+       outb(combase + com_dlbl, rate);
+       outb(combase + com_dlbh, rate >> 8);
+       outb(combase + com_cfcr, LCR_8BITS);
+       outb(combase + com_mcr, MCR_DTR | MCR_RTS);
+       outb(combase + com_fifo,
+           FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
+       outb(combase + com_ier, 0);
+
+       return speed;
+}
+
+/*
+ * return nonzero if input char available, do XON/XOFF handling
+ */
+int
+comstatus_d(int combase)
+{
+       /* check if any preread input is already there */
+       if (serbuf_read != serbuf_write) return 1;
+
+       /* check for new stuff on the port */
+       if (ISSET(inb(combase + com_lsr), LSR_RXRDY)) {
+               /* this could be XOFF, which we would swallow, so we can't
+                  claim there is input available... */
+               int c = inb(combase + com_data);
+               inb(combase + com_iir);
+               if (c == XOFF) {
+                       stopped = 1;
+               } else {
+                       /* stuff char into preread buffer */
+                       serbuf[serbuf_write++] = c;
+                       if (serbuf_write >= SERBUFSIZE)
+                               serbuf_write = 0;
+                       return 1;
+               }
+       }
+
+       return 0;       /* nothing out there... */
+}
diff --git a/sys/arch/i386/stand/lib/comio_direct.h b/sys/arch/i386/stand/lib/comio_direct.h
new file mode 100644 (file)
index 0000000..c4f9567
--- /dev/null
@@ -0,0 +1,6 @@
+/*     $NetBSD: comio_direct.h,v 1.4 2005/11/11 22:25:09 dsl Exp $     */
+
+int cominit_d(int, int);
+int computc_d(int, int);
+int comgetc_d(int);
+int comstatus_d(int);
diff --git a/sys/arch/i386/stand/lib/conio.S b/sys/arch/i386/stand/lib/conio.S
new file mode 100644 (file)
index 0000000..dd04a79
--- /dev/null
@@ -0,0 +1,126 @@
+/*     $NetBSD: conio.S,v 1.7 2011/06/16 13:27:59 joerg Exp $  */
+
+/* PC console handling
+  originally from: FreeBSD:sys/i386/boot/netboot/start2.S
+ */
+
+#include <machine/asm.h>
+
+       .text
+
+/**************************************************************************
+CLR - Clear screen
+**************************************************************************/
+ENTRY(conclr)
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       /* Clear screen. */
+       movw    $0x0600, %ax
+       movw    $0x0700, %bx
+       xorw    %cx, %cx
+       movw    $0x184f, %dx    /* 80x25 */
+       int     $0x10
+
+       /* Home cursor. */
+       movb    $0x02, %ah
+       xorw    %bx, %bx
+       xorw    %dx, %dx
+       int     $0x10
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       popa
+       ret
+
+/**************************************************************************
+PUTC - Print a character
+**************************************************************************/
+ENTRY(conputc)
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movw    $1,%bx
+       movb    $0x0e,%ah
+       movb    %al, %cl
+       int     $0x10
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       popa
+       ret
+
+/**************************************************************************
+GETC - Get a character
+**************************************************************************/
+ENTRY(congetc)
+       xorl    %eax, %eax
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x0,%ah
+       int     $0x16
+       movb    %al,%bl
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movb    %bl, 28(%esp)
+
+       popa
+       ret
+
+/**************************************************************************
+ISSHIFT - Check for keyboard interrupt; via shift key
+**************************************************************************/
+ENTRY(conisshift)
+       xorl    %eax, %eax
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       xor     %bx,%bx
+       movb    $0x2,%ah
+       int     $0x16
+       testb   $3,%al
+       setnz   %bl
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movb    %bl, 28(%esp)
+
+       popa
+       ret
+
+/**************************************************************************
+ISKEY - Check for keyboard input
+**************************************************************************/
+ENTRY(coniskey)
+       xorl    %eax, %eax
+       pusha
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       xor     %bx,%bx
+       movb    $0x1,%ah
+       int     $0x16
+       setnz   %bl
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movb    %bl, 28(%esp)
+
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/cpufunc.S b/sys/arch/i386/stand/lib/cpufunc.S
new file mode 100644 (file)
index 0000000..11570d1
--- /dev/null
@@ -0,0 +1,152 @@
+/*     $NetBSD: cpufunc.S,v 1.4 2011/06/08 16:03:42 joerg Exp $        */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+NENTRY(x86_read_psl)
+       pushfl
+       popl    %eax
+       ret
+
+NENTRY(x86_write_psl)
+       movl    4(%esp), %eax
+       pushl   %eax
+       popfl
+       ret
+
+NENTRY(x86_disable_intr)
+       cli
+       ret
+
+NENTRY(x86_enable_intr)
+       sti
+       ret
+
+NENTRY(inb)
+       movl    4(%esp), %edx
+       xorl    %eax, %eax
+       inb     %dx, %al
+       ret
+
+NENTRY(insb)
+       pushl   %edi
+       movl    8(%esp), %edx
+       movl    12(%esp), %edi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       insb
+       popl    %edi
+       ret
+
+NENTRY(inw)
+       movl    4(%esp), %edx
+       xorl    %eax, %eax
+       inw     %dx, %ax
+       ret
+
+NENTRY(insw)
+       pushl   %edi
+       movl    8(%esp), %edx
+       movl    12(%esp), %edi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       insw
+       popl    %edi
+       ret
+
+NENTRY(inl)
+       movl    4(%esp), %edx
+       inl     %dx, %eax
+       ret
+
+NENTRY(insl)
+       pushl   %edi
+       movl    8(%esp), %edx
+       movl    12(%esp), %edi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       insl
+       popl    %edi
+       ret
+
+NENTRY(outb)
+       movl    4(%esp), %edx
+       movl    8(%esp), %eax
+       outb    %al, %dx
+       ret
+
+NENTRY(outsb)
+       pushl   %esi
+       movl    8(%esp), %edx
+       movl    12(%esp), %esi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       outsb
+       popl    %esi
+       ret
+
+NENTRY(outw)
+       movl    4(%esp), %edx
+       movl    8(%esp), %eax
+       outw    %ax, %dx
+       ret
+
+NENTRY(outsw)
+       pushl   %esi
+       movl    8(%esp), %edx
+       movl    12(%esp), %esi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       outsw
+       popl    %esi
+       ret
+
+NENTRY(outl)
+       movl    4(%esp), %edx
+       movl    8(%esp), %eax
+       outl    %eax, %dx
+       ret
+
+NENTRY(outsl)
+       pushl   %esi
+       movl    8(%esp), %edx
+       movl    12(%esp), %esi
+       movl    16(%esp), %ecx
+       cld
+       rep
+       outsl
+       popl    %esi
+       ret
diff --git a/sys/arch/i386/stand/lib/cpufunc.h b/sys/arch/i386/stand/lib/cpufunc.h
new file mode 100644 (file)
index 0000000..856a3f1
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: cpufunc.h,v 1.2 2008/04/28 20:23:25 martin Exp $       */
+
+/*-
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void           x86_disable_intr(void);
+void           x86_enable_intr(void);
+u_long         x86_read_psl(void);
+void           x86_write_psl(u_long);
+
+u_int8_t       inb(unsigned);
+void           insb(unsigned, void *, int);
+uint16_t       inw(unsigned);
+void           insw(unsigned, void *, int);
+uint32_t       inl(unsigned);
+void           insl(unsigned, void *, int);
+
+void           outb(unsigned, uint8_t);
+void           outsb(unsigned, void *, int);
+void           outw(unsigned, uint16_t);
+void           outsw(unsigned, void *, int);
+void           outl(unsigned, uint32_t);
+void           outsl(unsigned, void *, int);
diff --git a/sys/arch/i386/stand/lib/crt/dos/doscommain.c b/sys/arch/i386/stand/lib/crt/dos/doscommain.c
new file mode 100644 (file)
index 0000000..93dc954
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $NetBSD: doscommain.c,v 1.6 2008/12/14 18:46:33 christos Exp $  */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* argument line processing for DOS .COM programs */
+
+#include <lib/libsa/stand.h>
+
+/* The Program Segment Prefix */
+
+static struct psp{
+       char mist1[0x2c];
+       short envseg;
+       char mist2[0x80-2-0x2c];
+       char cmdlen;
+       char cmd[127];
+} *PSP = (struct psp*)0;
+
+static char* argv[64]; /* theor max */
+
+static int whitespace(char);
+
+static int
+whitespace(char c)
+{
+       if ((c == '\0') || (c == ' ') || (c == '\t')
+           || (c == '\r') || (c == '\n'))
+               return (1);
+       return 0;
+}
+
+enum state {skipping, doing_arg, doing_long_arg};
+
+/* build argv/argc, start real main() */
+int doscommain(void);
+extern int main(int, char**);
+
+int
+doscommain(void)
+{
+       int argc, i;
+       enum state s;
+
+       argv[0] = "???"; /* we don't know */
+       argc = 1;
+       s = skipping;
+
+       for (i = 0; i < PSP->cmdlen; i++){
+
+               if (whitespace(PSP->cmd[i])) {
+                       if (s == doing_arg) {
+                               /* end of argument word */
+                               PSP->cmd[i] = '\0';
+                               s = skipping;
+                       }
+                       continue;
+               }
+
+               if (PSP->cmd[i] == '"') {
+                       /* start or end long arg
+                        * (end only if next char is whitespace)
+                        *  XXX but '" ' cannot be in argument
+                        */
+                       switch (s) {
+                       case skipping:
+                               /* next char begins new argument word */
+                               argv[argc++] = &PSP->cmd[i + 1];
+                               s = doing_long_arg;
+                               break;
+                       case doing_long_arg:
+                               if (whitespace(PSP->cmd[i + 1])) {
+                                       PSP->cmd[i] = '\0';
+                                       s = skipping;
+                               }
+                       case doing_arg:
+                               /* ignore in the middle of arguments */
+                       default:
+                               break;
+                       }
+                       continue;
+               }
+
+               /* all other characters */
+               if (s == skipping) {
+                       /* begin new argument word */
+                       argv[argc++] = &PSP->cmd[i];
+                       s = doing_arg;
+               }
+       }
+       if (s != skipping)
+               PSP->cmd[i] = '\0'; /* to be sure */
+
+       /* start real main() */
+       return main(argc, argv);
+}
diff --git a/sys/arch/i386/stand/lib/crt/dos/start_dos.S b/sys/arch/i386/stand/lib/crt/dos/start_dos.S
new file mode 100644 (file)
index 0000000..38eb43a
--- /dev/null
@@ -0,0 +1,620 @@
+/*     $NetBSD: start_dos.S,v 1.10 2010/12/20 01:12:44 jakllsch Exp $  */
+       
+/*
+ * startup for DOS .COM programs
+ * with input from:
+ * netbsd:sys/arch/i386/boot/start.S
+ * Tor Egge's patches for NetBSD boot (pr port-i386/1002)
+ * freebsd:sys/i386/boot/netboot/start2.S
+ * XMS support by Martin Husemann
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992 
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+
+
+CR0_PE         =       0x1
+
+       .data
+       .globl _C_LABEL(ourseg)
+_C_LABEL(ourseg):
+       .long   0
+
+/**************************************************************************
+GLOBAL DESCRIPTOR TABLE
+**************************************************************************/
+#ifdef __ELF__
+       .align  16
+#else
+       .align  4
+#endif
+gdt:
+       .word   0, 0
+       .byte   0, 0x00, 0x00, 0
+
+#ifdef SUPPORT_LINUX   /* additional dummy */
+       .word   0, 0
+       .byte   0, 0x00, 0x00, 0
+#endif
+
+       /* kernel code segment */
+       .globl flatcodeseg
+flatcodeseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9f, 0xcf, 0
+
+       /* kernel data segment */
+       .globl flatdataseg
+flatdataseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x93, 0xcf, 0
+
+       /* boot code segment, base will be patched */
+bootcodeseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9e, 0x40, 0
+
+       /* boot data segment, base will be patched */
+bootdataseg = . - gdt
+#ifdef HEAP_BELOW_64K
+       .word   0xffff, 0
+       .byte   0, 0x92, 0x00, 0
+#else
+       .word   0xffff, 0
+       .byte   0, 0x92, 0x4f, 0
+#endif
+
+       /* 16 bit real mode, base will be patched */
+bootrealseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9e, 0x00, 0
+
+       /* limits (etc) for data segment in real mode */
+bootrealdata = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x92, 0x00, 0
+gdtlen = . - gdt
+
+#ifdef __ELF__
+       .align  16
+#else
+       .align  4
+#endif
+gdtarg:
+       .word   gdtlen-1                /* limit */
+       .long   0                       /* addr, will be inserted */
+
+       .text
+ENTRY(start)
+       .code16
+
+       # Check we are in real mode
+       movl    %cr0, %eax
+       testl   $CR0_PE, %eax
+       jz      2f
+       mov     $1f, %si
+       call    message
+       ret
+1:     .asciz  "must be in real mode\r\n"
+2:
+
+       xorl    %eax, %eax
+       mov     %cs, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+       movl    %eax, _C_LABEL(ourseg)
+#ifdef STACK_START
+       add     $STACK_START / 16, %ax
+       mov     %ax, %ss
+       mov     $0xfffc, %sp
+#endif
+
+       /* fix up GDT entries for bootstrap */
+#define FIXUP(gdt_index) \
+       movw    %ax, gdt+gdt_index+2;   \
+       movb    %bl, gdt+gdt_index+4
+
+       mov     %cs, %ax
+       shll    $4, %eax
+       shldl   $16, %eax, %ebx
+       FIXUP(bootcodeseg)
+       FIXUP(bootrealseg)
+       FIXUP(bootdataseg)
+
+       /* fix up GDT pointer */
+       addl    $gdt, %eax
+       movl    %eax, gdtarg+2
+
+       /* change to protected mode */
+       calll   _C_LABEL(real_to_prot)
+       .code32
+
+       /* clear the bss */
+       movl    $_C_LABEL(edata), %edi
+       movl    $_C_LABEL(end), %ecx
+       subl    %edi, %ecx
+       xorb    %al, %al
+       rep
+       stosb
+
+       call    _C_LABEL(doscommain)
+ENTRY(_rtt)
+       call    _C_LABEL(prot_to_real)
+       .code16
+ENTRY(exit16)
+       sti
+       movb    $0x4c, %ah              /* return */
+       int     $0x21
+
+/*
+ * real_to_prot()
+ *     transfer from real mode to protected mode.
+ */
+ENTRY(real_to_prot)
+       .code16
+       pushl   %eax
+       # guarantee that interrupt is disabled when in prot mode
+       cli
+
+       # load the gdtr
+       lgdtl   %cs:gdtarg
+
+       # set the PE bit of CR0
+       movl    %cr0, %eax
+       orl     $CR0_PE, %eax
+       movl    %eax, %cr0 
+
+       # make intrasegment jump to flush the processor pipeline and
+       # reload CS register
+       ljmp    $bootcodeseg, $xprot
+
+xprot:
+       .code32
+       # we are in USE32 mode now
+       # set up the protected mode segment registers : DS, SS, ES
+       movl    $bootdataseg, %eax
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %ss
+#ifdef STACK_START
+       addl    $STACK_START, %esp
+#endif
+
+       popl    %eax
+       ret
+
+/*
+ * prot_to_real()
+ *     transfer from protected mode to real mode
+ */
+ENTRY(prot_to_real)
+       .code32
+       pushl   %eax
+       # set up a dummy stack frame for the second seg change.
+       # Adjust the intersegment jump instruction following 
+       # the clearing of protected mode bit.
+       # This is self-modifying code, but we need a writable
+       # code segment, and an intersegment return does not give us that.
+
+       movl    _C_LABEL(ourseg), %eax
+       movw    %ax, xreal-2
+
+       /*
+        * Load the segment registers while still in protected mode.
+        * Otherwise the control bits don't get changed.
+        * The correct values are loaded later.
+        */
+       movw    $bootrealdata, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %ss
+
+       # Change to use16 mode.
+       ljmp    $bootrealseg, $x16
+
+x16:
+       .code16
+       # clear the PE bit of CR0
+       movl    %cr0, %eax
+       andl    $~CR0_PE, %eax
+       movl    %eax, %cr0
+
+       # Here we have an 16 bits intersegment jump.
+       ljmp    $0, $xreal              /* segment patched above */
+
+xreal:
+       # we are in real mode now
+       # set up the real mode segment registers : DS, SS, ES
+       mov     %cs, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+#ifdef STACK_START
+       add     $STACK_START / 16, %ax
+       mov     %ax, %ss
+       subl    $STACK_START, %esp
+#else
+       mov     %ax, %ss
+#endif
+       push    %bp
+       movw    %sp, %bp
+       /* check we are returning to an address below 64k */
+       movw    2/*bp*/ + 4/*eax*/ + 2(%bp), %ax        /* high bits ret addr */
+       test    %ax, %ax
+       jne     1f
+       pop     %bp
+
+       sti
+       popl    %eax
+       retl
+
+1:     movw    $2f, %si
+       call    message
+       movl    2/*bp*/ + 4/*eax*/(%bp), %eax           /*  return address */
+       call    dump_eax
+       jmp     exit16
+2:     .asciz  "prot_to_real can't return to "
+
+
+/**************************************************************************
+___MAIN - Dummy to keep GCC happy
+**************************************************************************/
+ENTRY(__main)
+       ret
+
+/*
+ * pbzero(dst, cnt)
+ *     where dst is a physical address and cnt is the length
+ */
+ENTRY(pbzero)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %es
+       pushl   %edi
+
+       cld
+
+       # set %es to point at the flat segment
+       movl    $flatdataseg, %eax
+       mov     %ax, %es
+
+       movl    8(%ebp), %edi           # destination
+       movl    12(%ebp), %ecx          # count
+       xorl    %eax, %eax              # value
+
+       rep
+       stosb
+
+       popl    %edi
+       popl    %es
+       popl    %ebp
+       ret
+
+/*
+ * vpbcopy(src, dst, cnt)
+ *     where src is a virtual address and dst is a physical address
+ */
+ENTRY(vpbcopy)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %es
+       pushl   %esi
+       pushl   %edi
+
+       cld
+
+       # set %es to point at the flat segment
+       movl    $flatdataseg, %eax
+       mov     %ax, %es
+
+       movl    8(%ebp), %esi           # source
+       movl    12(%ebp), %edi          # destination
+       movl    16(%ebp), %ecx          # count
+
+       rep
+       movsb
+
+       popl    %edi
+       popl    %esi
+       popl    %es
+       popl    %ebp
+       ret
+
+/*
+ * pvbcopy(src, dst, cnt)
+ *     where src is a physical address and dst is a virtual address
+ */
+ENTRY(pvbcopy)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ds
+       pushl   %esi
+       pushl   %edi
+
+       cld
+
+       # set %ds to point at the flat segment
+       movl    $flatdataseg, %eax
+       mov     %ax, %ds
+
+       movl    8(%ebp), %esi           # source
+       movl    12(%ebp), %edi          # destination
+       movl    16(%ebp), %ecx          # count
+
+       rep
+       movsb
+
+       popl    %edi
+       popl    %esi
+       popl    %ds
+       popl    %ebp
+       ret
+
+ENTRY(vtophys)
+       .code32
+       movl    _C_LABEL(ourseg), %eax
+       shll    $4, %eax
+       addl    4(%esp), %eax
+       ret
+
+message:
+       .code16
+       pushal
+message_1:
+       cld
+1:     lodsb
+       testb   %al, %al
+       jz      2f
+       movb    $0xe, %ah
+       movw    $1, %bx
+       int     $0x10
+       jmp     1b
+
+2:     movb    $0x86, %ah
+       mov     $16, %cx
+       int     $0x15                   /* delay about a second */
+       popal
+       ret
+
+/* These are useful for debugging
+ */
+       .data
+eax_buf:
+       .long   0, 0, 0, 0
+       .text
+ENTRY(dump_eax)
+       .code16
+       pushal
+       movw    $eax_buf, %si
+       mov     %si, %di
+       movw    $8, %cx
+1:     roll    $4, %eax
+       mov     %ax, %bx
+       andb    $0x0f, %al
+       addb    $0x30, %al                      /* 30..3f - clear AF */
+#if 1 /* 5 bytes to generate real hex... */
+       daa                                     /* 30..39, 40..45 */
+       addb    $0xc0, %al                      /* f0..f9, 00..05 */
+       adcb    $0x40, %al                      /* 30..39, 41..45 */
+#endif
+       movb    %al, (%di)                      /* %es != %ds, so can't ... */
+       inc     %di                             /* ... use stosb */
+       mov     %bx, %ax
+       loop    1b
+       movw    $0x20, %ax                      /* space + null */
+       movw    %ax, (%di)
+       jmp     message_1
+
+       .globl  _C_LABEL(trace_word)
+_C_LABEL(trace_word):
+       .code32
+       movl    4(%esp), %edx
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+       movl    %edx, %eax
+       call    dump_eax
+       calll   _C_LABEL(real_to_prot)
+       .code32
+       ret
+
+       .globl  _C_LABEL(trace_str)
+_C_LABEL(trace_str):
+       .code32
+       pushl   %esi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+       mov     %sp, %si
+       mov     8(%si), %si
+       call    message
+       calll   _C_LABEL(real_to_prot)
+       .code32
+       popl    %esi
+       ret
+
+#ifdef XMS
+
+/* pointer to XMS driver, 0 if no XMS used */
+
+       .data
+_C_LABEL(xmsdrv):
+       .long   0
+
+       .text
+ENTRY(checkxms)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %edx
+       pushl   %es
+       pushl   %esi
+       pushl   %edi
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movw    $0x4300, %ax
+       int     $0x2f                   /* check if XMS installed */
+       cmpb    $0x80, %al
+       jnz     noxms
+
+       movw    $0x4310, %ax
+       int     $0x2f                   /* get driver address */
+
+       movw    %bx, _C_LABEL(xmsdrv)   /* save es:bx to _xmsdrv */
+       movw    %es, _C_LABEL(xmsdrv) + 2
+
+       movb    $0x08, %ah              /* XMS: query free extended memory */
+#if 0
+       movb    $0x00, %bl
+#endif
+       lcall   *_C_LABEL(xmsdrv)
+       jmp     xdone
+
+noxms:         /* no XMS manager found */
+       mov     $0, %dx
+
+xdone:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       xorl    %eax, %eax
+       movw    %dx, %ax
+
+       popl    %edi
+       popl    %esi
+       popl    %es
+       popl    %edx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+       Allocate a block of XMS memory with the requested size
+               void *xmsalloc(long int kBytes);
+
+       Depends on _xmsdrv being set by getextmem() before first call
+       to this function.
+
+       Return value: a physical address.
+*/
+ENTRY(xmsalloc)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %edx
+       pushl   %esi
+       pushl   %edi
+
+       movl    0x8(%ebp), %edx # Kbytes needed
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x09, %ah              # XMS allocate block
+       lcall   *_C_LABEL(xmsdrv)       # result: handle in %dx
+       movb    $0x0c, %ah              # XMS lock block
+       lcall   *_C_LABEL(xmsdrv)       # result: 32 bit physical addr in DX:BX
+
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %edx, %eax
+       shl     $16, %eax
+       movw    %bx, %ax        # result in %eax
+
+       popl    %edi
+       popl    %esi
+       popl    %edx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ * ppbcopy(src, dst, cnt)
+ *     where src and dst are physical addresses
+ */
+ENTRY(ppbcopy)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %es
+       pushl   %esi
+       pushl   %edi
+
+       cld
+
+       # set %es to point at the flat segment
+       movl    $flatdataseg, %eax
+       mov     %ax, %es
+
+       movl    8(%ebp), %esi           # source
+       movl    12(%ebp), %edi          # destination
+       movl    16(%ebp), %ecx          # count
+
+       es
+       rep
+       movsb
+
+       popl    %edi
+       popl    %esi
+       popl    %es
+       popl    %ebp
+       ret
+
+#endif
diff --git a/sys/arch/i386/stand/lib/diskbuf.c b/sys/arch/i386/stand/lib/diskbuf.c
new file mode 100644 (file)
index 0000000..645cf75
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: diskbuf.c,v 1.6 2005/12/11 12:17:48 christos Exp $     */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* data buffer for BIOS disk / DOS I/O  */
+
+#include <lib/libsa/stand.h>
+#include "diskbuf.h"
+
+char *diskbufp;                /* allocated from heap */
+
+const void *diskbuf_user;
+
+/*
+ * Global shared "diskbuf" is used as read ahead buffer.
+ * This MAY have to not cross a 64k boundary.
+ * In practise it is allocated out of the heap early on...
+ * NB a statically allocated diskbuf is not guaranteed to not
+ * cross a 64k boundary.
+ */
+char *
+alloc_diskbuf(const void *user)
+{
+       diskbuf_user = user;
+       if (!diskbufp) {
+               diskbufp = alloc(DISKBUFSIZE);
+               if (((int)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) {
+                       printf("diskbufp %x\n", (unsigned)diskbufp);
+                       panic("diskbuf crosses 64k boundary");
+               }
+       }
+       return diskbufp;
+}
diff --git a/sys/arch/i386/stand/lib/diskbuf.h b/sys/arch/i386/stand/lib/diskbuf.h
new file mode 100644 (file)
index 0000000..a4b9fea
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: diskbuf.h,v 1.4 2005/12/11 12:17:48 christos Exp $     */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* data buffer for BIOS disk / DOS I/O */
+
+#ifndef DISKBUFSIZE
+/* Read ahead buffer large enough for one track on a 1440K floppy.
+ */
+#define DISKBUFSIZE (18*512)
+#endif
+
+extern char *diskbufp;         /* allocated from heap... */
+extern const void *diskbuf_user; /* using function sets it to unique
+                           value to allow check if overwritten*/
+char *alloc_diskbuf(const void *);
diff --git a/sys/arch/i386/stand/lib/dos_file.S b/sys/arch/i386/stand/lib/dos_file.S
new file mode 100644 (file)
index 0000000..1c5547d
--- /dev/null
@@ -0,0 +1,203 @@
+/*     $NetBSD: dos_file.S,v 1.6 2009/11/21 11:52:57 dsl Exp $ */
+       
+/* extracted from Tor Egge's patches for NetBSD boot */
+
+#include <machine/asm.h>
+
+/*
+# MSDOS call "INT 0x21 Function 0x3d" to open a file.
+# Call with    %ah = 0x3d
+#              %al = 0x0  (access and sharing modes)
+#              %ds:%dx = ASCIZ filename
+#              %cl = attribute mask of files to look for
+*/
+
+       .globl _C_LABEL(doserrno)
+_C_LABEL(doserrno):    .long 1
+
+ENTRY(dosopen)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %edx
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+       
+       movl    0x8(%ebp), %edx         # File name.
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %ds
+       movl    %edx, %eax
+       shrl    $4, %eax
+       mov     %ds, %si
+       add     %si, %ax
+       mov     %ax, %ds
+       and     $0xf, %dx
+
+       movb    $0x3d, %ah              # Open existing file.
+       movb    $0x0 , %al              # ro
+
+       sti
+       int     $0x21
+       cli
+       pop     %ds
+
+       jnc     ok1
+       mov     %ax, _C_LABEL(doserrno)
+       movl    $-1, %edx
+       jmp err1
+ok1:
+       movl    $0,%edx
+       mov     %ax, %dx
+err1:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       popl    %edx
+       popl    %ebp
+       ret
+
+ENTRY(dosread)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %esi
+       pushl   %edi
+       
+       movl    0x8(%ebp), %ebx         # File handle
+       movl    0xc(%ebp), %edx         # Buffer.
+       movl    0x10(%ebp), %ecx        # Bytes to read
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       push    %ds
+       movl    %edx, %eax
+       shrl    $4, %eax
+       mov     %ds, %si
+       add     %si, %ax
+       mov     %ax, %ds
+       and     $0xf, %dx
+
+       movb    $0x3f, %ah              # Read from file or device
+
+       sti
+       int     $0x21
+       cli
+       pop     %ds
+
+       jnc     ok2
+       mov     %ax, _C_LABEL(doserrno)
+       movl    $-1, %edx
+       jmp     err2
+ok2:
+       movl    $0,%edx
+       mov     %ax, %dx
+err2:
+       calll   _C_LABEL(real_to_prot)  # back to protected mode
+       .code32
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
+
+ENTRY(dosclose)
+       .code32
+       pushl %ebp
+       movl  %esp, %ebp
+       pushl   %ebx
+       pushl   %esi
+       pushl   %edi
+       
+       movl    0x8(%ebp), %ebx         # File handle
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x3e, %ah              # Close file.
+
+       sti
+       int     $0x21
+       cli
+
+       jnc     ok3
+       mov     %ax, _C_LABEL(doserrno)
+       movl    $-1, %ebx
+       jmp     err3
+ok3:
+       movl    $0, %ebx
+err3:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %ebx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %esi
+       popl    %ebx
+       popl    %ebp
+       ret
+
+ENTRY(dosseek)
+       .code32
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %ebx
+       pushl   %ecx
+       pushl   %edx
+       pushl   %esi
+       pushl   %edi
+       
+       movl    0x8(%ebp), %ebx         # File handle
+       movl    0xc(%ebp), %ecx         # Offset
+       movl    0x10(%ebp) , %edx       # whence
+
+       call    _C_LABEL(prot_to_real)  # enter real mode
+       .code16
+
+       movb    $0x42, %ah              # Seek
+       movb    %dl, %al                # whence
+       mov     %cx, %dx                #offs lo
+       shrl    $0x10, %ecx             #offs hi
+
+       sti
+       int     $0x21
+       cli
+
+       jnc     ok4
+       mov     %ax, _C_LABEL(doserrno)
+       movl    $-1, %edx
+       jmp     err4
+ok4:
+       shll    $0x10, %edx     #new ofs hi
+       mov     %ax, %dx        #new ofs lo
+err4:
+       calll   _C_LABEL(real_to_prot) # back to protected mode
+       .code32
+
+       movl    %edx, %eax              # return value in %eax
+
+       popl    %edi
+       popl    %esi
+       popl    %edx
+       popl    %ecx
+       popl    %ebx
+       popl    %ebp
+       ret
diff --git a/sys/arch/i386/stand/lib/dosfile.c b/sys/arch/i386/stand/lib/dosfile.c
new file mode 100644 (file)
index 0000000..e2ab313
--- /dev/null
@@ -0,0 +1,240 @@
+/*     $NetBSD: dosfile.c,v 1.15 2011/06/16 13:27:59 joerg Exp $        */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * DOS filesystem for libsa
+ * standalone - uses no device, works only with DOS running
+ * needs lowlevel parts from dos_file.S
+ */
+
+#include <lib/libsa/stand.h>
+
+#include "diskbuf.h"
+#include "dosfile.h"
+
+extern int dosopen(const char *);
+extern void dosclose(int);
+extern int dosread(int, char *, int);
+extern int dosseek(int, int, int);
+
+struct dosfile {
+       int doshandle, off;
+};
+
+extern int doserrno;   /* in dos_file.S */
+
+static int dos2errno(void);
+
+static int
+dos2errno(void)
+{
+       int err;
+
+       switch (doserrno) {
+           case 1:
+           case 4:
+           case 12:
+           default:
+               err = EIO;
+           case 2:
+           case 3:
+               err = ENOENT;
+           case 5:
+               err = EPERM;
+           case 6:
+               err = EINVAL;
+       }
+       return err;
+}
+
+__compactcall int
+dos_open(const char *path, struct open_file *f)
+{
+       struct dosfile *df;
+
+       df = (struct dosfile *) alloc(sizeof(*df));
+       if (!df)
+               return -1;
+
+       df->off = 0;
+       df->doshandle = dosopen(path);
+       if (df->doshandle < 0) {
+#ifdef DEBUG
+               printf("DOS error %d\n", doserrno);
+#endif
+               dealloc(df, sizeof(*df));
+               return dos2errno();
+       }
+       f->f_fsdata = (void *) df;
+       return 0;
+}
+
+__compactcall int
+dos_read(struct open_file *f, void *addr, size_t size, size_t *resid)
+{
+       struct dosfile *df;
+       int             got;
+       static int      tc = 0;
+
+       df = (struct dosfile *) f->f_fsdata;
+
+       if (!(tc++ % 4))
+               twiddle();
+
+       if ((unsigned long) addr >= 0x10000) {
+               u_int           lsize = size;
+
+               while (lsize > 0) {
+                       u_int           tsize;
+                       size_t          tgot;
+                       char            *p = addr;
+
+                       tsize = lsize;
+
+                       if (tsize > DISKBUFSIZE)
+                               tsize = DISKBUFSIZE;
+
+                       alloc_diskbuf(dos_read);
+
+                       tgot = dosread(df->doshandle, diskbufp, tsize);
+                       if (tgot < 0) {
+#ifdef DEBUG
+                               printf("DOS error %d\n", doserrno);
+#endif
+                               return dos2errno();
+                       }
+                       memcpy(p, diskbufp, tgot);
+
+                       p += tgot;
+                       lsize -= tgot;
+
+                       if (tgot != tsize)
+                               break;  /* EOF */
+               }
+               got = size - lsize;
+       } else {
+               got = dosread(df->doshandle, addr, size);
+
+               if (got < 0) {
+#ifdef DEBUG
+                       printf("DOS error %d\n", doserrno);
+#endif
+                       return dos2errno();
+               }
+       }
+
+       df->off += got;
+       size -= got;
+
+       if (resid)
+               *resid = size;
+       return 0;
+}
+
+__compactcall int
+dos_close(struct open_file *f)
+{
+       struct dosfile *df;
+       df = (struct dosfile *) f->f_fsdata;
+
+       dosclose(df->doshandle);
+
+       if (df)
+               dealloc(df, sizeof(*df));
+       return 0;
+}
+
+__compactcall int
+dos_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       return EROFS;
+}
+
+__compactcall int
+dos_stat(struct open_file *f, struct stat *sb)
+{
+       struct dosfile *df;
+       df = (struct dosfile *) f->f_fsdata;
+
+       sb->st_mode = 0444;
+       sb->st_nlink = 1;
+       sb->st_uid = 0;
+       sb->st_gid = 0;
+       sb->st_size = -1;
+       return 0;
+}
+
+__compactcall off_t
+dos_seek(struct open_file *f, off_t offset, int where)
+{
+       struct dosfile *df;
+       int             doswhence, res;
+#ifdef DOS_CHECK
+       int             checkoffs;
+#endif
+       df = (struct dosfile *) f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               doswhence = 0;
+#ifdef DOS_CHECK
+               checkoffs = offset;     /* don't trust DOS */
+#endif
+               break;
+       case SEEK_CUR:
+               doswhence = 1;
+#ifdef DOS_CHECK
+               checkoffs = df->off + offset;
+#endif
+               break;
+       case SEEK_END:
+               doswhence = 2;
+#ifdef DOS_CHECK
+               checkoffs = -1; /* we dont know len */
+#endif
+               break;
+       default:
+               errno = EOFFSET;
+               return -1;
+       }
+       res = dosseek(df->doshandle, offset, doswhence);
+       if (res == -1) {
+               errno = dos2errno();
+               return -1;
+       }
+#ifdef DOS_CHECK
+       if ((checkoffs != -1) && (res != checkoffs)) {
+               printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n",
+                      df->off, offset, where, res);
+               errno = EOFFSET;
+               return -1;
+       }
+#endif
+       df->off = res;
+       return res;
+}
diff --git a/sys/arch/i386/stand/lib/dosfile.h b/sys/arch/i386/stand/lib/dosfile.h
new file mode 100644 (file)
index 0000000..ccffbd0
--- /dev/null
@@ -0,0 +1,29 @@
+/*     $NetBSD: dosfile.h,v 1.4 2005/12/11 12:17:48 christos Exp $     */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+FS_DEF(dos);
diff --git a/sys/arch/i386/stand/lib/dump_eax.S b/sys/arch/i386/stand/lib/dump_eax.S
new file mode 100644 (file)
index 0000000..f2d646c
--- /dev/null
@@ -0,0 +1,59 @@
+/*     $NetBSD: dump_eax.S,v 1.4 2009/11/19 22:08:14 dsl Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/* This is useful for debugging - although you may need to
+ * delete some code to fit it in.
+ * %ds:dump_eax_buff must be somewhere it is safe to write 10 bytes.
+ */
+
+ENTRY(dump_eax)
+       .code16
+       pusha                                   /* saves bottom 16 bits only! */
+       movw    $dump_eax_buff, %si
+       mov     %si, %di
+       movw    $8, %cx
+1:     roll    $4, %eax
+       push    %ax
+       andb    $0x0f, %al
+       addb    $0x30, %al                      /* 30..3f - clear AF */
+#if 1 /* 5 bytes to generate real hex... */
+       daa                                     /* 30..39, 40..45 */
+       addb    $0xc0, %al                      /* f0..f9, 00..05 */
+       adcb    $0x40, %al                      /* 30..39, 41..46 */
+#endif
+       mov     %al,(%di)
+       inc     %di
+       pop     %ax
+       loop    1b
+       movw    $0x20,(%di)                     /* space + NIL */
+       jmp     message_1
diff --git a/sys/arch/i386/stand/lib/exec.c b/sys/arch/i386/stand/lib/exec.c
new file mode 100644 (file)
index 0000000..45abbe1
--- /dev/null
@@ -0,0 +1,743 @@
+/*     $NetBSD: exec.c,v 1.49 2011/11/28 07:56:54 tls Exp $     */
+
+/*-
+ * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)boot.c      8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996
+ *     Perry E. Metzger.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)boot.c      8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * starts NetBSD a.out kernel
+ * needs lowlevel startup from startprog.S
+ * This is a special version of exec.c to support use of XMS.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/reboot.h>
+
+#include <machine/multiboot.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include "loadfile.h"
+#include "libi386.h"
+#include "bootinfo.h"
+#include "bootmod.h"
+#include "vbe.h"
+#ifdef SUPPORT_PS2
+#include "biosmca.h"
+#endif
+
+#define BOOT_NARGS     6
+
+#ifndef        PAGE_SIZE
+#define        PAGE_SIZE       4096
+#endif
+
+#define MODULE_WARNING_SEC     5
+
+extern struct btinfo_console btinfo_console;
+
+boot_module_t *boot_modules;
+bool boot_modules_enabled = true;
+bool kernel_loaded;
+
+typedef struct userconf_command {
+       char *uc_text;
+       size_t uc_len;
+       struct userconf_command *uc_next;
+} userconf_command_t;
+userconf_command_t *userconf_commands = NULL;
+
+static struct btinfo_framebuffer btinfo_framebuffer;
+
+static struct btinfo_modulelist *btinfo_modulelist;
+static size_t btinfo_modulelist_size;
+static uint32_t image_end;
+static char module_base[64] = "/";
+static int howto;
+
+static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL;
+static size_t btinfo_userconfcommands_size = 0;
+
+static void    module_init(const char *);
+static void    module_add_common(char *, uint8_t);
+
+static void    userconf_init(void);
+
+void
+framebuffer_configure(struct btinfo_framebuffer *fb)
+{
+       if (fb)
+               btinfo_framebuffer = *fb;
+       else {
+               btinfo_framebuffer.physaddr = 0;
+               btinfo_framebuffer.flags = 0;
+       }
+}
+
+void
+module_add(char *name)
+{
+       return module_add_common(name, BM_TYPE_KMOD);
+}
+
+void
+splash_add(char *name)
+{
+       return module_add_common(name, BM_TYPE_IMAGE);
+}
+
+void
+rnd_add(char *name)
+{
+       return module_add_common(name, BM_TYPE_RND);
+}
+
+static void
+module_add_common(char *name, uint8_t type)
+{
+       boot_module_t *bm, *bmp;
+       size_t len;
+       char *str;
+
+       while (*name == ' ' || *name == '\t')
+               ++name;
+
+       bm = alloc(sizeof(boot_module_t));
+       len = strlen(name) + 1;
+       str = alloc(len);
+       if (bm == NULL || str == NULL) {
+               printf("couldn't allocate module\n");
+               return;
+       }
+       memcpy(str, name, len);
+       bm->bm_path = str;
+       bm->bm_next = NULL;
+       bm->bm_type = type;
+       if (boot_modules == NULL)
+               boot_modules = bm;
+       else {
+               for (bmp = boot_modules; bmp->bm_next;
+                   bmp = bmp->bm_next)
+                       ;
+               bmp->bm_next = bm;
+       }
+}
+
+void
+userconf_add(char *cmd)
+{
+       userconf_command_t *uc;
+       size_t len;
+       char *text;
+
+       while (*cmd == ' ' || *cmd == '\t')
+               ++cmd;
+
+       uc = alloc(sizeof(*uc));
+       if (uc == NULL) {
+               printf("couldn't allocate command\n");
+               return;
+       }
+
+       len = strlen(cmd) + 1;
+       text = alloc(len);
+       if (text == NULL) {
+               dealloc(uc, sizeof(*uc));
+               printf("couldn't allocate command\n");
+               return;
+       }
+       memcpy(text, cmd, len);
+
+       uc->uc_text = text;
+       uc->uc_len = len;
+       uc->uc_next = NULL;
+
+       if (userconf_commands == NULL)
+               userconf_commands = uc;
+       else {
+               userconf_command_t *ucp;
+               for (ucp = userconf_commands; ucp->uc_next != NULL;
+                    ucp = ucp->uc_next)
+                       ;
+               ucp->uc_next = uc;
+       }
+}
+
+static int
+common_load_kernel(const char *file, u_long *basemem, u_long *extmem,
+    physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
+{
+       int fd;
+#ifdef XMS
+       u_long          xmsmem;
+       physaddr_t      origaddr = loadaddr;
+#endif
+
+       *extmem = getextmem();
+       *basemem = getbasemem();
+
+#ifdef XMS
+       if ((getextmem1() == 0) && (xmsmem = checkxms())) {
+               u_long kernsize;
+
+               /*
+                * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
+                *  getextmem() is getextmem1(). Without, the "smart"
+                *  methods could fail to report all memory as well.
+                * xmsmem is a few kB less than the actual size, but
+                *  better than nothing.
+                */
+               if (xmsmem > *extmem)
+                       *extmem = xmsmem;
+               /*
+                * Get the size of the kernel
+                */
+               marks[MARK_START] = loadaddr;
+               if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
+                       return EIO;
+               close(fd);
+
+               kernsize = marks[MARK_END];
+               kernsize = (kernsize + 1023) / 1024;
+
+               loadaddr = xmsalloc(kernsize);
+               if (!loadaddr)
+                       return ENOMEM;
+       }
+#endif
+       marks[MARK_START] = loadaddr;
+       if ((fd = loadfile(file, marks,
+           LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
+               return EIO;
+
+       close(fd);
+
+       /* Now we know the root fs type, load modules for it. */
+       module_add(fsmod);
+       if (fsmod2 != NULL && strcmp(fsmod, fsmod2) != 0)
+               module_add(fsmod2);
+
+       /*
+        * Gather some information for the kernel. Do this after the
+        * "point of no return" to avoid memory leaks.
+        * (but before DOS might be trashed in the XMS case)
+        */
+#ifdef PASS_BIOSGEOM
+       bi_getbiosgeom();
+#endif
+#ifdef PASS_MEMMAP
+       bi_getmemmap();
+#endif
+
+#ifdef XMS
+       if (loadaddr != origaddr) {
+               /*
+                * We now have done our last DOS IO, so we may
+                * trash the OS. Copy the data from the temporary
+                * buffer to its real address.
+                */
+               marks[MARK_START] -= loadaddr;
+               marks[MARK_END] -= loadaddr;
+               marks[MARK_SYM] -= loadaddr;
+               marks[MARK_END] -= loadaddr;
+               ppbcopy(loadaddr, origaddr, marks[MARK_END]);
+       }
+#endif
+       marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
+           (-sizeof(int));
+       image_end = marks[MARK_END];
+       kernel_loaded = true;
+
+       return 0;
+}
+
+int
+exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
+           void (*callback)(void))
+{
+       u_long          boot_argv[BOOT_NARGS];
+       u_long          marks[MARK_MAX];
+       struct btinfo_symtab btinfo_symtab;
+       u_long          extmem;
+       u_long          basemem;
+
+#ifdef DEBUG
+       printf("exec: file=%s loadaddr=0x%lx\n",
+              file ? file : "NULL", loadaddr);
+#endif
+
+       BI_ALLOC(32); /* ??? */
+
+       BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
+
+       howto = boothowto;
+
+       if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks))
+               goto out;
+
+       boot_argv[0] = boothowto;
+       boot_argv[1] = 0;
+       boot_argv[2] = vtophys(bootinfo);       /* old cyl offset */
+       boot_argv[3] = marks[MARK_END];
+       boot_argv[4] = extmem;
+       boot_argv[5] = basemem;
+
+       /* pull in any modules if necessary */
+       if (boot_modules_enabled) {
+               module_init(file);
+               if (btinfo_modulelist) {
+                       BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
+                           btinfo_modulelist_size);
+               }
+       }
+
+       userconf_init();
+       if (btinfo_userconfcommands != NULL)
+               BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS,
+       btinfo_userconfcommands_size);
+
+#ifdef DEBUG
+       printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
+           marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
+#endif
+
+       btinfo_symtab.nsym = marks[MARK_NSYM];
+       btinfo_symtab.ssym = marks[MARK_SYM];
+       btinfo_symtab.esym = marks[MARK_END];
+       BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
+
+       /* set new video mode if necessary */
+       vbe_commit();
+       BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER,
+           sizeof(struct btinfo_framebuffer));
+
+       if (callback != NULL)
+               (*callback)();
+       startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
+                 x86_trunc_page(basemem*1024));
+       panic("exec returned");
+
+out:
+       BI_FREE();
+       bootinfo = 0;
+       return -1;
+}
+
+static void
+extract_device(const char *path, char *buf, size_t buflen)
+{
+       int i;
+
+       if (strchr(path, ':') != NULL) {
+               for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
+                       buf[i] = path[i];
+               buf[i++] = ':';
+               buf[i] = '\0';
+       } else
+               buf[0] = '\0';
+}
+
+static const char *
+module_path(boot_module_t *bm, const char *kdev)
+{
+       static char buf[256];
+       char name_buf[256], dev_buf[64];
+       const char *name, *name2, *p;
+
+       name = bm->bm_path;
+       for (name2 = name; *name2; ++name2) {
+               if (*name2 == ' ' || *name2 == '\t') {
+                       strlcpy(name_buf, name, sizeof(name_buf));
+                       if (name2 - name < sizeof(name_buf))
+                               name_buf[name2 - name] = '\0';
+                       name = name_buf;
+                       break;
+               }
+       }
+       if ((p = strchr(name, ':')) != NULL) {
+               /* device specified, use it */
+               if (p[1] == '/')
+                       snprintf(buf, sizeof(buf), "%s", name);
+               else {
+                       p++;
+                       extract_device(name, dev_buf, sizeof(dev_buf));
+                       snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
+                           dev_buf, module_base, p, p);
+               }
+       } else {
+               /* device not specified; load from kernel device if known */
+               if (name[0] == '/')
+                       snprintf(buf, sizeof(buf), "%s%s", kdev, name);
+               else
+                       snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
+                           kdev, module_base, name, name);
+       }
+
+       return buf;
+}
+
+static int
+module_open(boot_module_t *bm, int mode, const char *kdev, bool doload)
+{
+       int fd;
+       const char *path;
+
+       /* check the expanded path first */
+       path = module_path(bm, kdev);
+       fd = open(path, mode);
+       if (fd != -1) {
+               if ((howto & AB_SILENT) == 0 && doload)
+                       printf("Loading %s ", path);
+       } else {
+               /* now attempt the raw path provided */
+               fd = open(bm->bm_path, mode);
+               if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
+                       printf("Loading %s ", bm->bm_path);
+       }
+       if (!doload && fd == -1) {
+               printf("WARNING: couldn't open %s", bm->bm_path);
+               if (strcmp(bm->bm_path, path) != 0)
+                       printf(" (%s)", path);
+               printf("\n");
+       }
+       return fd;
+}
+
+static void
+module_init(const char *kernel_path)
+{
+       struct bi_modulelist_entry *bi;
+       struct stat st;
+       const char *machine;
+       char kdev[64];
+       char *buf;
+       boot_module_t *bm;
+       size_t len;
+       off_t off;
+       int err, fd, nfail = 0;
+
+       extract_device(kernel_path, kdev, sizeof(kdev));
+
+       switch (netbsd_elf_class) {
+       case ELFCLASS32:
+               machine = "i386";
+               break;
+       case ELFCLASS64:
+               machine = "amd64";
+               break;
+       default:
+               machine = "generic";
+               break;
+       }
+       if (netbsd_version / 1000000 % 100 == 99) {
+               /* -current */
+               snprintf(module_base, sizeof(module_base),
+                   "/stand/%s/%d.%d.%d/modules", machine,
+                   netbsd_version / 100000000,
+                   netbsd_version / 1000000 % 100,
+                   netbsd_version / 100 % 100);
+       } else if (netbsd_version != 0) {
+               /* release */
+               snprintf(module_base, sizeof(module_base),
+                   "/stand/%s/%d.%d/modules", machine,
+                   netbsd_version / 100000000,
+                   netbsd_version / 1000000 % 100);
+       }
+
+       /* First, see which modules are valid and calculate btinfo size */
+       len = sizeof(struct btinfo_modulelist);
+       for (bm = boot_modules; bm; bm = bm->bm_next) {
+               fd = module_open(bm, 0, kdev, false);
+               if (fd == -1) {
+                       bm->bm_len = -1;
+                       ++nfail;
+                       continue;
+               }
+               err = fstat(fd, &st);
+               if (err == -1 || st.st_size == -1) {
+                       printf("WARNING: couldn't stat %s\n", bm->bm_path);
+                       close(fd);
+                       bm->bm_len = -1;
+                       ++nfail;
+                       continue;
+               }
+               bm->bm_len = st.st_size;
+               close(fd);
+               len += sizeof(struct bi_modulelist_entry);
+       }
+
+       /* Allocate the module list */
+       btinfo_modulelist = alloc(len);
+       if (btinfo_modulelist == NULL) {
+               printf("WARNING: couldn't allocate module list\n");
+               wait_sec(MODULE_WARNING_SEC);
+               return;
+       }
+       memset(btinfo_modulelist, 0, len);
+       btinfo_modulelist_size = len;
+
+       /* Fill in btinfo structure */
+       buf = (char *)btinfo_modulelist;
+       btinfo_modulelist->num = 0;
+       off = sizeof(struct btinfo_modulelist);
+
+       for (bm = boot_modules; bm; bm = bm->bm_next) {
+               if (bm->bm_len == -1)
+                       continue;
+               fd = module_open(bm, 0, kdev, true);
+               if (fd == -1)
+                       continue;
+               image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+               len = pread(fd, (void *)image_end, SSIZE_MAX);
+               if (len < bm->bm_len) {
+                       if ((howto & AB_SILENT) != 0)
+                               printf("Loading %s ", bm->bm_path);
+                       printf(" FAILED\n");
+               } else {
+                       btinfo_modulelist->num++;
+                       bi = (struct bi_modulelist_entry *)(buf + off);
+                       off += sizeof(struct bi_modulelist_entry);
+                       strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
+                       bi->base = image_end;
+                       bi->len = len;
+                       switch (bm->bm_type) {
+                           case BM_TYPE_KMOD:
+                               bi->type = BI_MODULE_ELF;
+                               break;
+                           case BM_TYPE_IMAGE:
+                               bi->type = BI_MODULE_IMAGE;
+                               break;
+                           case BM_TYPE_RND:
+                           default:
+                               /* safest -- rnd checks the sha1 */
+                               bi->type = BI_MODULE_RND;
+                               break;
+                       }
+                       if ((howto & AB_SILENT) == 0)
+                               printf(" \n");
+               }
+               if (len > 0)
+                       image_end += len;
+               close(fd);
+       }
+       btinfo_modulelist->endpa = image_end;
+
+       if (nfail > 0) {
+               printf("WARNING: %d module%s failed to load\n",
+                   nfail, nfail == 1 ? "" : "s");
+#if notyet
+               wait_sec(MODULE_WARNING_SEC);
+#endif
+       }
+}
+
+static void
+userconf_init(void)
+{
+       size_t count, len;
+       userconf_command_t *uc;
+       char *buf;
+       off_t off;
+
+       /* Calculate the userconf commands list size */
+       count = 0;
+       for (uc = userconf_commands; uc != NULL; uc = uc->uc_next)
+               count++;
+       len = sizeof(btinfo_userconfcommands) +
+             count * sizeof(struct bi_userconfcommand);
+
+       /* Allocate the userconf commands list */
+       btinfo_userconfcommands = alloc(len);
+       if (btinfo_userconfcommands == NULL) {
+               printf("WARNING: couldn't allocate userconf commands list\n");
+               return;
+       }
+       memset(btinfo_userconfcommands, 0, len);
+       btinfo_userconfcommands_size = len;
+
+       /* Fill in btinfo structure */
+       buf = (char *)btinfo_userconfcommands;
+       off = sizeof(*btinfo_userconfcommands);
+       btinfo_userconfcommands->num = 0;
+       for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) {
+               struct bi_userconfcommand *bi;
+               bi = (struct bi_userconfcommand *)(buf + off);
+               strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1);
+
+               off += sizeof(*bi);
+               btinfo_userconfcommands->num++;
+       }
+}
+
+int
+exec_multiboot(const char *file, char *args)
+{
+       struct multiboot_info *mbi;
+       struct multiboot_module *mbm;
+       struct bi_modulelist_entry *bim;
+       int             i, len;
+       u_long          marks[MARK_MAX];
+       u_long          extmem;
+       u_long          basemem;
+       char            *cmdline;
+
+       mbi = alloc(sizeof(struct multiboot_info));
+       mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY;
+
+       if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks))
+               goto out;
+
+       mbi->mi_mem_upper = extmem;
+       mbi->mi_mem_lower = basemem;
+
+       if (args) {
+               mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE;
+               len = strlen(file) + 1 + strlen(args) + 1;
+               cmdline = alloc(len);
+               snprintf(cmdline, len, "%s %s", file, args);
+               mbi->mi_cmdline = (char *) vtophys(cmdline);
+       }
+
+       /* pull in any modules if necessary */
+       if (boot_modules_enabled) {
+               module_init(file);
+               if (btinfo_modulelist) {
+                       mbm = alloc(sizeof(struct multiboot_module) *
+                                          btinfo_modulelist->num);
+
+                       bim = (struct bi_modulelist_entry *)
+                         (((char *) btinfo_modulelist) +
+                          sizeof(struct btinfo_modulelist));
+                       for (i = 0; i < btinfo_modulelist->num; i++) {
+                               mbm[i].mmo_start = bim->base;
+                               mbm[i].mmo_end = bim->base + bim->len;
+                               mbm[i].mmo_string = (char *)vtophys(bim->path);
+                               mbm[i].mmo_reserved = 0;
+                               bim++;
+                       }
+                       mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS;
+                       mbi->mi_mods_count = btinfo_modulelist->num;
+                       mbi->mi_mods_addr = vtophys(mbm);
+               }
+       }
+
+#ifdef DEBUG
+       printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
+           marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
+#endif
+
+
+#if 0
+       if (btinfo_symtab.nsym) {
+               mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS;
+               mbi->mi_elfshdr_addr = marks[MARK_SYM];
+       btinfo_symtab.nsym = marks[MARK_NSYM];
+       btinfo_symtab.ssym = marks[MARK_SYM];
+       btinfo_symtab.esym = marks[MARK_END];
+#endif
+
+       multiboot(marks[MARK_ENTRY], vtophys(mbi),
+                 x86_trunc_page(mbi->mi_mem_lower*1024));
+       panic("exec returned");
+
+out:
+        dealloc(mbi, 0);
+       return -1;
+}
+
+void
+x86_progress(const char *fmt, ...)
+{
+       va_list ap;
+
+       if ((howto & AB_SILENT) != 0)
+               return;
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+}
diff --git a/sys/arch/i386/stand/lib/gatea20.c b/sys/arch/i386/stand/lib/gatea20.c
new file mode 100644 (file)
index 0000000..a5ab0bf
--- /dev/null
@@ -0,0 +1,80 @@
+/*     $NetBSD: gatea20.c,v 1.12 2009/08/23 12:31:05 jmcneill Exp $    */
+
+/* extracted from freebsd:sys/i386/boot/biosboot/io.c */
+
+#include <sys/types.h>
+
+#include <lib/libsa/stand.h>
+
+#include "libi386.h"
+#include "biosmca.h"
+#include "cpufunc.h"
+
+#define K_RDWR                 0x60            /* keyboard data & cmds (read/write) */
+#define K_STATUS       0x64            /* keyboard status */
+#define K_CMD          0x64            /* keybd ctlr command (write-only) */
+
+#define K_OBUF_FUL     0x01            /* output buffer full */
+#define K_IBUF_FUL     0x02            /* input buffer full */
+
+#define KC_CMD_WIN     0xd0            /* read  output port */
+#define KC_CMD_WOUT    0xd1            /* write output port */
+#define KB_A20         0x9f            /* enable A20,
+                                          reset (!),
+                                          enable output buffer full interrupt
+                                          enable data line
+                                          disable clock line */
+
+/*
+ * Gate A20 for high memory
+ */
+static unsigned char   x_20 = KB_A20;
+
+void
+gateA20(void)
+{
+       int biosA20(void);
+       u_long psl;
+
+       /*
+        * First, try asking the BIOS to enable A20.
+        *
+        * If that fails, try system configuration port 0x92 but only
+        * if known to be necessary.  Not all systems enable A20 via the
+        * keyboard controller, some don't have keyboard controllers,
+        * and playing with port 0x92 may cause some systems to break.
+        *
+        * Otherwise, use the traditional method (keyboard controller).
+        */
+       if (!biosA20())
+               return;
+       psl = x86_read_psl();
+       x86_disable_intr();
+       if (
+#ifdef SUPPORT_PS2
+           biosmca_ps2model == 0xf82 ||
+#endif
+           (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) {
+               int data;
+
+               data = inb(0x92);
+               outb(0x92, data | 0x2);
+       } else {
+               while (inb(K_STATUS) & K_IBUF_FUL);
+
+               while (inb(K_STATUS) & K_OBUF_FUL)
+                       (void)inb(K_RDWR);
+
+               outb(K_CMD, KC_CMD_WOUT);
+
+               while (inb(K_STATUS) & K_IBUF_FUL);
+
+               outb(K_RDWR, x_20);
+
+               while (inb(K_STATUS) & K_IBUF_FUL);
+
+               while (inb(K_STATUS) & K_OBUF_FUL)
+                       (void)inb(K_RDWR);
+       }
+       x86_write_psl(psl);
+}
diff --git a/sys/arch/i386/stand/lib/getextmemx.c b/sys/arch/i386/stand/lib/getextmemx.c
new file mode 100644 (file)
index 0000000..b305d65
--- /dev/null
@@ -0,0 +1,93 @@
+/*     $NetBSD: getextmemx.c,v 1.10 2011/06/16 13:27:59 joerg Exp $    */
+
+/*
+ * Copyright (c) 1997, 1999
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Try 2 more fancy BIOS calls to get the size of extended
+ * memory besides the classical int15/88, take maximum.
+ * needs lowlevel parts from biosmemx.S and biosmem.S
+ */
+
+#include <lib/libsa/stand.h>
+#include "libi386.h"
+
+int
+getextmemx(void)
+{
+       int buf[5], i;
+       int extmem = getextmem1();
+#ifdef SUPPORT_PS2
+       struct {
+               uint16_t len;
+               uint32_t dta[8];
+               /* pad to 64 bytes - without this, machine would reset */
+               uint8_t __pad[30];
+       } __packed bufps2;
+#endif
+
+#ifdef DEBUG_MEMSIZE
+       printf("extmem1: %xk\n", extmem);
+#endif
+       if (!getextmem2(buf)) {
+#ifdef DEBUG_MEMSIZE
+               printf("extmem2: %xk + %xk\n", buf[0], buf[1] * 64);
+#endif
+               if (buf[0] <= 15 * 1024) {
+                       int help = buf[0];
+                       if (help == 15 * 1024)
+                               help += buf[1] * 64;
+                       if (extmem < help)
+                               extmem = help;
+               }
+       }
+
+       i = 0;
+       do {
+               if (getmementry(&i, buf))
+                       break;
+#ifdef DEBUG_MEMSIZE
+               printf("mementry: (%d) %x %x %x %x %x\n",
+                       i, buf[0], buf[1], buf[2], buf[3], buf[4]);
+#endif
+               if ((buf[4] == 1 && buf[0] == 0x100000)
+                   && extmem < buf[2] / 1024)
+                       extmem = buf[2] / 1024;
+       } while (i);
+
+#ifdef SUPPORT_PS2
+       /* use local memory information from RETURN MEMORY-MAP INFORMATION */
+       if (!getextmemps2((void *) &bufps2)) {
+               int help = bufps2.dta[0];
+               if (help == 15 * 1024)
+                       help += bufps2.dta[1];
+               if (extmem < help)
+                       extmem = help;
+       }
+#endif
+
+       return extmem;
+}
diff --git a/sys/arch/i386/stand/lib/getsecs.c b/sys/arch/i386/stand/lib/getsecs.c
new file mode 100644 (file)
index 0000000..e5c9daa
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: getsecs.c,v 1.4 2009/01/12 11:32:44 tsutsui Exp $      */
+
+/* extracted from netbsd:sys/arch/i386/netboot/misc.c */
+
+#include <sys/types.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/net.h>
+
+#include "libi386.h"
+
+static inline u_long bcd2dec(u_long);
+
+static inline u_long
+bcd2dec(u_long arg)
+{
+       return (arg >> 4) * 10 + (arg & 0x0f);
+}
+
+satime_t
+getsecs(void) {
+       /*
+        * Return the current time in seconds
+        */
+
+       u_long t;
+       satime_t sec;
+
+       if (biosgetrtc(&t))
+               panic("RTC invalid");
+
+       sec = bcd2dec(t & 0xff);
+       sec *= 60;
+       t >>= 8;
+       sec += bcd2dec(t & 0xff);
+       sec *= 60;
+       t >>= 8;
+       sec += bcd2dec(t & 0xff);
+
+       return sec;
+}
diff --git a/sys/arch/i386/stand/lib/isadma.c b/sys/arch/i386/stand/lib/isadma.c
new file mode 100644 (file)
index 0000000..acd47ab
--- /dev/null
@@ -0,0 +1,43 @@
+/*     $NetBSD: isadma.c,v 1.2 2008/12/14 17:03:43 christos Exp $      */
+
+/* from: NetBSD:dev/isa/isadma.c */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+
+#include "isadmavar.h"
+
+#define        IO_DMA1         0x000           /* 8237A DMA Controller #1 */
+#define        IO_DMA2         0x0C0           /* 8237A DMA Controller #2 */
+#define        DMA37MD_CASCADE 0xc0    /* cascade mode */
+#define        DMA1_SMSK       (IO_DMA1 + 1*10)        /* single mask register */
+#define        DMA1_MODE       (IO_DMA1 + 1*11)        /* mode register */
+#define        DMA2_SMSK       (IO_DMA2 + 2*10)        /* single mask register */
+#define        DMA2_MODE       (IO_DMA2 + 2*11)        /* mode register */
+
+/*
+ * isa_dmacascade(): program 8237 DMA controller channel to accept
+ * external dma control by a board.
+ */
+void
+isa_dmacascade(int chan)
+{
+
+#ifdef ISADMA_DEBUG
+       if (chan < 0 || chan > 7)
+               panic("isa_dmacascade: impossible request");
+#endif
+
+       /* set dma channel mode, and set dma channel mode */
+       if ((chan & 4) == 0) {
+               outb(DMA1_MODE, chan | DMA37MD_CASCADE);
+               outb(DMA1_SMSK, chan);
+       } else {
+               chan &= 3;
+
+               outb(DMA2_MODE, chan | DMA37MD_CASCADE);
+               outb(DMA2_SMSK, chan);
+       }
+}
diff --git a/sys/arch/i386/stand/lib/isadmavar.h b/sys/arch/i386/stand/lib/isadmavar.h
new file mode 100644 (file)
index 0000000..f3b9139
--- /dev/null
@@ -0,0 +1,3 @@
+/*     $NetBSD: isadmavar.h,v 1.2 2008/12/14 17:03:43 christos Exp $   */
+
+void isa_dmacascade(int);
diff --git a/sys/arch/i386/stand/lib/isapnp.c b/sys/arch/i386/stand/lib/isapnp.c
new file mode 100644 (file)
index 0000000..cd3ba5f
--- /dev/null
@@ -0,0 +1,231 @@
+/*     $NetBSD: isapnp.c,v 1.5 2008/12/14 17:03:43 christos Exp $       */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * minimal ISA PnP implementation: find adapter, return settings (1 IO and 1
+ * DMA only for now)
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+
+#include "isapnpvar.h"
+
+#define PNPADDR 0x0279
+#define PNPWDATA 0x0a79
+#define PNPRDATAMIN 0x0203
+#define PNPRDATAMAX 0x03ff
+
+enum {
+       DATAPORT,
+       ISOL,
+       CONTROL,
+       WAKE,
+       RESDATA,
+       RESSTAT,
+       SETCSN,
+       SETLDEV
+};
+
+#define MEMBASE 0x40
+#define IOBASE 0x60
+#define INTBASE 0x70
+#define DMABASE 0x74
+
+static int      pnpdataport;
+
+static int
+getiobase(int nr)
+{
+       unsigned short  iobase;
+
+       outb(PNPADDR, SETLDEV);
+       outb(PNPWDATA, 0);      /* subdev 0 */
+
+       outb(PNPADDR, IOBASE + nr * 2);
+       iobase = (inb(pnpdataport) << 8);
+       outb(PNPADDR, IOBASE + nr * 2 + 1);
+       iobase |= inb(pnpdataport);
+
+       return iobase;
+}
+
+static int
+getdmachan(int nr)
+{
+       unsigned char   dmachannel;
+
+       outb(PNPADDR, SETLDEV);
+       outb(PNPWDATA, 0);      /* subdev 0 */
+
+       outb(PNPADDR, DMABASE + nr);
+       dmachannel = inb(pnpdataport) & 0x07;
+
+       return dmachannel;
+}
+
+struct cardid {
+       unsigned char   eisaid[4];
+       unsigned int    serial;
+       unsigned char   crc;
+};
+
+/*
+ do isolation, call pnpscanresc() in board config state
+ */
+static int
+pnpisol(int csn)
+{
+       unsigned char   buf[9];
+       int             i, j;
+       struct cardid  *id;
+       unsigned char   crc = 0x6a;
+
+       /*
+        * do 72 pairs of reads from ISOL register all but 1 go to sleep
+        * state (ch. 3.3)
+        */
+       outb(PNPADDR, ISOL);
+       delay(1000);
+
+       for (i = 0; i < 9; i++) {
+               for (j = 0; j < 8; j++) {
+                       unsigned char   a, b;
+                       int             bitset;
+
+                       a = inb(pnpdataport);
+                       b = inb(pnpdataport);
+                       if ((a == 0x55) && (b == 0xaa))
+                               bitset = 1;
+                       else if ((a == 0xff) && (b == 0xff))
+                               bitset = 0;
+                       else
+                               return -1;      /* data port conflict */
+
+                       buf[i] = (buf[i] >> 1) | (bitset << 7);
+
+                       if (i < 8)      /* calc crc for first 8 bytes (app.
+                                        * B.2) */
+                               crc = (crc >> 1) |
+                                 ((bitset != ((crc & 1) == !(crc & 2))) << 7);
+
+                       delay(250);
+               }
+       }
+       id = (struct cardid *) buf;
+
+       if (id->crc != crc)
+               return 0;       /* normal end */
+
+       outb(PNPADDR, SETCSN);
+       outb(PNPWDATA, csn);    /* set csn for winning card and put it to
+                                * config state */
+
+       return (id->eisaid[0] << 24) | (id->eisaid[1] << 16)
+               | (id->eisaid[2] << 8) | (id->eisaid[3]);
+}
+
+static void
+pnpisolreset(void)
+{
+       outb(PNPADDR, WAKE);
+       outb(PNPWDATA, 0);      /* put all remaining cards to isolation state */
+}
+
+/*
+ send initiation sequence (app. B.1)
+ */
+static void
+pnpinit(void)
+{
+       int             i;
+       unsigned char   key = 0x6a;
+
+       outb(PNPADDR, 0);
+       outb(PNPADDR, 0);
+
+       for (i = 0; i < 32; i++) {
+               outb(PNPADDR, key);
+               key = (key >> 1) |
+                       (((key & 1) == !(key & 2)) << 7);
+       }
+}
+
+int
+isapnp_finddev(int id, int *iobase, int *dmachan)
+{
+       int             csn;
+
+       outb(PNPADDR, CONTROL);
+       outb(PNPWDATA, 2);      /* XXX force wait for key */
+
+       /* scan all allowed data ports (ch. 3.1) */
+       for (pnpdataport = PNPRDATAMIN; pnpdataport <= PNPRDATAMAX;
+            pnpdataport += 4) {
+               int             res, found = 0;
+
+               pnpinit();      /* initiation sequence */
+
+               outb(PNPADDR, CONTROL);
+               outb(PNPWDATA, 4);      /* CSN=0 - only these respond to
+                                        * WAKE[0] */
+
+               outb(PNPADDR, WAKE);
+               outb(PNPWDATA, 0);      /* put into isolation state */
+
+               outb(PNPADDR, DATAPORT);
+               outb(PNPWDATA, pnpdataport >> 2);       /* set READ_DATA port */
+
+               csn = 0;
+               do {
+                       res = pnpisol(++csn);
+
+                       if ((res) == id) {
+                               if (iobase)
+                                       *iobase = getiobase(0);
+                               if (dmachan)
+                                       *dmachan = getdmachan(0);
+                               found = 1;
+                       }
+                       pnpisolreset();
+               } while ((res != 0) && (res != -1));
+
+               outb(PNPADDR, CONTROL);
+               outb(PNPWDATA, 2);      /* return to wait for key */
+
+               if (csn > 1)    /* at least 1 board found */
+                       return !found;
+
+               /* if no board found, try next dataport */
+       }
+       return -1;              /* nothing found */
+}
diff --git a/sys/arch/i386/stand/lib/isapnpvar.h b/sys/arch/i386/stand/lib/isapnpvar.h
new file mode 100644 (file)
index 0000000..41b05fe
--- /dev/null
@@ -0,0 +1,29 @@
+/*     $NetBSD: isapnpvar.h,v 1.4 2008/12/14 17:03:43 christos Exp $   */
+
+/*
+ * Copyright (c) 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+int isapnp_finddev(int, int*, int*);
diff --git a/sys/arch/i386/stand/lib/libi386.h b/sys/arch/i386/stand/lib/libi386.h
new file mode 100644 (file)
index 0000000..2fb0ec5
--- /dev/null
@@ -0,0 +1,145 @@
+/*     $NetBSD: libi386.h,v 1.38 2011/11/28 07:56:54 tls Exp $ */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+typedef unsigned long physaddr_t;
+
+/* this is in startup code */
+void vpbcopy(const void *, void *, size_t);
+void pvbcopy(const void *, void *, size_t);
+void pbzero(void *, size_t);
+physaddr_t vtophys(void *);
+
+ssize_t pread(int, void *, size_t);
+void startprog(physaddr_t, int, unsigned long *, physaddr_t);
+void multiboot(physaddr_t, physaddr_t, physaddr_t);
+
+int exec_netbsd(const char *, physaddr_t, int, int, void (*)(void));
+int exec_multiboot(const char *, char *);
+
+void delay(int);
+int getbasemem(void);
+int getextmemx(void);
+int getextmem1(void);
+int biosvideomode(void);
+#ifdef CONSERVATIVE_MEMDETECT
+#define getextmem() getextmem1()
+#else
+#define getextmem() getextmemx()
+#endif
+void printmemlist(void);
+void reboot(void);
+void gateA20(void);
+
+void clear_pc_screen(void);
+void initio(int);
+#define CONSDEV_PC 0
+#define CONSDEV_COM0 1
+#define CONSDEV_COM1 2
+#define CONSDEV_COM2 3
+#define CONSDEV_COM3 4
+#define CONSDEV_COM0KBD 5
+#define CONSDEV_COM1KBD 6
+#define CONSDEV_COM2KBD 7
+#define CONSDEV_COM3KBD 8
+#define CONSDEV_AUTO (-1)
+int iskey(int);
+char awaitkey(int, int);
+void wait_sec(int);
+
+/* this is in "user code"! */
+int parsebootfile(const char *, char **, char **, int *, int *, const char **);
+
+#ifdef XMS
+physaddr_t ppbcopy(physaddr_t, physaddr_t, int);
+int checkxms(void);
+physaddr_t xmsalloc(int);
+#endif
+
+/* parseutils.c */
+char *gettrailer(char *);
+int parseopts(const char *, int *);
+int parseboot(char *, char **, int *);
+
+/* menuutils.c */
+struct bootblk_command {
+       const char *c_name;
+       void (*c_fn)(char *);
+};
+void bootmenu(void);
+void docommand(char *);
+
+/* in "user code": */
+void command_help(char *);
+extern const struct bootblk_command commands[];
+
+/* asm bios/dos calls */
+__compactcall int biosdisk_extread(int, void *);
+int biosdisk_read(int, int, int, int, int, void *);
+__compactcall int biosdisk_reset(int);
+
+__compactcall int biosgetrtc(u_long *);
+int biosgetsystime(void);
+int comgetc(int);
+void cominit(int);
+__compactcall int computc(int, int);
+int comstatus(int);
+int congetc(void);
+int conisshift(void);
+int coniskey(void);
+__compactcall void conputc(int);
+void conclr(void);
+
+int getextmem2(int *);
+__compactcall int getextmemps2(void *);
+int getmementry(int *, int *);
+
+__compactcall int biosdisk_int13ext(int);
+__compactcall int biosdisk_getinfo(int);
+struct biosdisk_extinfo;
+__compactcall int biosdisk_getextinfo(int, struct biosdisk_extinfo *);
+int get_harddrives(void);
+void biosdisk_probe(void);
+
+int pcibios_cfgread(unsigned int, int, int *);
+int pcibios_cfgwrite(unsigned int, int, int);
+int pcibios_finddev(int, int, int, unsigned int *);
+int pcibios_present(int *);
+
+void dosclose(int);
+int dosopen(char *);
+int dosread(int, char *, int);
+int dosseek(int, int, int);
+extern int doserrno;   /* in dos_file.S */
+
+void module_add(char *);
+void splash_add(char *);
+void rnd_add(char *);
+void userconf_add(char *);
+
+struct btinfo_framebuffer;
+void framebuffer_configure(struct btinfo_framebuffer *);
diff --git a/sys/arch/i386/stand/lib/menuutils.c b/sys/arch/i386/stand/lib/menuutils.c
new file mode 100644 (file)
index 0000000..92904ac
--- /dev/null
@@ -0,0 +1,84 @@
+/*     $NetBSD: menuutils.c,v 1.3 2008/12/14 18:46:33 christos Exp $   */
+
+/*
+ * Copyright (c) 1996, 1997
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996, 1997
+ *     Perry E. Metzger.  All rights reserved.
+ * Copyright (c) 1997
+ *     Jason R. Thorpe.  All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Matthias Drochner.
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include "libi386.h"
+
+void
+docommand(char *arg)
+{
+       char *options;
+       int i;
+
+       options = gettrailer(arg);
+
+       for (i = 0; commands[i].c_name != NULL; i++) {
+               if (strcmp(arg, commands[i].c_name) == 0) {
+                       (*commands[i].c_fn)(options);
+                       return;
+               }
+       }
+
+       printf("unknown command\n");
+       command_help(NULL);
+}
+
+void
+bootmenu(void)
+{
+       char input[80];
+
+       for (;;) {
+               char *c = input;
+
+               input[0] = '\0';
+               printf("> ");
+               gets(input);
+
+               /*
+                * Skip leading whitespace.
+                */
+               while (*c == ' ')
+                       c++;
+               if (*c)
+                       docommand(c);
+       }
+}
diff --git a/sys/arch/i386/stand/lib/message.S b/sys/arch/i386/stand/lib/message.S
new file mode 100644 (file)
index 0000000..21a7081
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $NetBSD: message.S,v 1.4 2009/11/19 22:10:03 dsl Exp $  */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+       .global message, message_1
+
+#if defined(BOOT_MSG_COM0) && !defined(COM_PORT_VAL)
+#define COM_PORT_VAL $0x3f8            /* Value for COM1 */
+#endif
+
+/*
+ * message: write the error message in %ds:%esi to the console
+ */
+message:
+/*
+ * BIOS call "INT 10H Function 0Eh" to write character to console
+ *     Call with       %ah = 0x0e
+ *                     %al = character
+ *                     %bh = page
+ *                     %bl = foreground color
+ */
+       .code16
+       pusha
+message_1:                     /* for dump_eax */
+       lodsb
+1:
+#ifdef COM_PORT_VAL
+       mov     COM_PORT_VAL, %dx
+       outb    %al, %dx
+       add     $5, %dl
+2:     inb     %dx
+       test    $0x40, %al
+       jz      2b
+#else
+       movb    $0x0e, %ah
+       movw    $0x0001, %bx
+       int     $0x10
+#endif
+       lodsb
+       testb   %al, %al
+       jnz     1b
+
+#ifdef MESSAGE_PAUSE
+       /* Delay for about 1 second to allow message to be read */
+       movb    $0x86, %ah
+       mov     $16, %cx                /* about a second */
+       int     $0x15                   /* delay cx:dx usecs */
+#endif
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/message32.S b/sys/arch/i386/stand/lib/message32.S
new file mode 100644 (file)
index 0000000..45cd286
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: message32.S,v 1.1 2009/11/19 22:13:17 dsl Exp $        */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/* 
+ * Output messages directly to serial port from 32bit mode.
+ * Useful for debugging when the real-prot is suspect.
+ *
+ * %ds:dump_eax_buff must be somewhere it is safe to write 12 bytes.
+ */
+
+#ifndef COM_PORT_VAL
+#define COM_PORT_VAL $0x3f8    /* Standard address COM1 (dty0) */
+#endif
+
+       .globl  message32
+       .code32
+message32:
+       pusha   
+message32_1:
+       lodsb   
+2:
+       mov     COM_PORT_VAL, %dx
+       outb    %al, %dx
+       add     $5, %dl
+3:      inb     %dx
+       test    $0x40, %al
+       jz      3b
+
+       lodsb
+       test    %al, %al
+       jnz     2b
+       popa
+       ret     
+
+       .globl  dump_eax32
+dump_eax32:
+       pusha
+       movl    $dump_eax_buff, %esi
+       mov     %esi, %edi
+       push    $8
+       pop     %ecx
+1:     roll    $4, %eax
+       push    %eax
+       andb    $0x0f, %al
+       addb    $0x30, %al                      /* 30..3f - clear AF */
+#if 1 /* 5 bytes to generate real hex... */
+       daa                                     /* 30..39, 40..45 */
+       addb    $0xc0, %al                      /* f0..f9, 00..05 */
+       adcb    $0x40, %al                      /* 30..39, 41..46 */
+#endif
+       movb    %al,(%edi)
+       inc     %edi
+       pop     %eax
+       loop    1b
+       push    $0x20                           /* space + 3 NULs */
+       pop     (%edi)
+       jmp     message32_1
diff --git a/sys/arch/i386/stand/lib/multiboot.S b/sys/arch/i386/stand/lib/multiboot.S
new file mode 100644 (file)
index 0000000..de52259
--- /dev/null
@@ -0,0 +1,124 @@
+/*     $NetBSD: multiboot.S,v 1.1 2008/10/11 11:06:20 joerg Exp $      */
+       
+/* starts program in protected mode / flat space
+ with given stackframe
+ needs global variables flatcodeseg and flatdataseg
+ (gdt offsets)
+  derived from: NetBSD:sys/arch/i386/stand/lib/startprog.S
+ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992 
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+#define MULTIBOOT_INFO_MAGIC           0x2BADB002
+
+/*
+ * multiboot(phyaddr,header,stack)
+ *     start the program on protected mode where phyaddr is the entry point
+ */
+ENTRY(multiboot)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       # prepare a new stack
+       movl    $flatdataseg, %eax
+       movw    %ax, %es                # for arg copy
+       movl    16(%ebp), %ebx  # stack
+       subl    $4,%ebx
+       movl    %ebx, %edi
+
+       movl    12(%ebp), %ebx  # header        
+       movl    8(%ebp), %ecx   # entry
+
+       # set new stackptr (movsl decd sp 1 more -> dummy return address)
+       movw    %ax, %ss
+       movl    %edi, %esp
+
+       # push on our entry address
+       movl    $flatcodeseg, %eax              # segment
+       pushl   %eax
+       pushl   %ecx                    #entry
+
+       # convert over the other data segs
+       movl    $flatdataseg, %eax
+       mov     %ax, %ds
+       mov     %ax, %es
+
+       movl    $MULTIBOOT_INFO_MAGIC, %eax
+       # convert the PC (and code seg)
+       lret
diff --git a/sys/arch/i386/stand/lib/netif/3c509.c b/sys/arch/i386/stand/lib/netif/3c509.c
new file mode 100644 (file)
index 0000000..ea60802
--- /dev/null
@@ -0,0 +1,227 @@
+/*     $NetBSD: 3c509.c,v 1.10 2008/12/14 18:46:33 christos Exp $      */
+
+/* stripped down from freebsd:sys/i386/netboot/3c509.c */
+
+/**************************************************************************
+NETBOOT -  BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters.
+  Date: Mar 22 1995
+
+ This code is based heavily on David Greenman's if_ed.c driver and
+  Andres Vega Garcia's if_ep.c driver.
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+  This software may be used, modified, copied, distributed, and sold, in
+  both source and binary form provided that the above copyright and these
+  terms are retained. Under no circumstances are the authors responsible for
+  the proper functioning of this software, nor do the authors assume any
+  responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp
+
+***************************************************************************/
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#ifdef _STANDALONE
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+#include "3c509.h"
+
+unsigned ether_medium;
+unsigned short eth_base;
+
+extern void epreset(void);
+extern int ep_get_e(int);
+
+static int send_ID_sequence(int);
+static int get_eeprom_data(int, int);
+
+u_char eth_myaddr[6];
+
+static struct mtabentry {
+    int address_cfg; /* configured connector */
+    int config_bit; /* connector present */
+    char *name;
+} mediatab[] = { /* indexed by media type - etherdrv.h */
+    {3, IS_BNC, "BNC"},
+    {0, IS_UTP, "UTP"},
+    {1, IS_AUI, "AUI"},
+};
+
+#ifdef _STANDALONE
+static struct btinfo_netif bi_netif;
+#endif
+
+#ifndef _STANDALONE
+extern int mapio(void);
+#endif
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+int
+EtherInit(unsigned char *myadr)
+{
+       /* common variables */
+       int i;
+       /* variables for 3C509 */
+       int data, j, id_port = EP_ID_PORT;
+       u_short k;
+/*     int ep_current_tag = EP_LAST_TAG + 1; */
+       u_short *p;
+       struct mtabentry *m;
+
+#ifndef _STANDALONE
+       if (mapio()) {
+               printf("no IO access\n");
+               return 0;
+       }
+#endif
+
+       /*********************************************************
+                       Search for 3Com 509 card
+       ***********************************************************/
+/*
+       ep_current_tag--;
+*/
+
+       /* Look for the ISA boards. Init and leave them actived */
+       /* search for the first card, ignore all others */
+       outb(id_port, 0xc0);    /* Global reset */
+       delay(1000);
+/*
+       for (i = 0; i < EP_MAX_BOARDS; i++) {
+*/
+               outb(id_port, 0);
+               outb(id_port, 0);
+               send_ID_sequence(id_port);
+
+               data = get_eeprom_data(id_port, EEPROM_MFG_ID);
+               if (data != MFG_ID)
+                       return 0;
+
+               /* resolve contention using the Ethernet address */
+               for (j = 0; j < 3; j++)
+                       data = get_eeprom_data(id_port, j);
+
+               eth_base =
+                   (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
+               outb(id_port, EP_LAST_TAG);     /* tags board */
+               outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
+/*
+               ep_current_tag--;
+               break;
+       }
+
+       if (i == EP_MAX_BOARDS)
+               return 0;
+*/
+
+       /*
+       * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
+       * 0x9[0-f]50
+       */
+       GO_WINDOW(0);
+       k = (u_int)ep_get_e(EEPROM_PROD_ID);
+       if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
+               return 0;
+
+       printf("3C5x9 board on ISA at 0x%x - ", eth_base);
+
+       /* test for presence of connectors */
+       i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
+       j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14;
+
+       for (ether_medium = 0, m = mediatab;
+           ether_medium < sizeof(mediatab) / sizeof(mediatab[0]);
+           ether_medium++, m++) {
+           if (j == m->address_cfg) {
+               if (!(i & m->config_bit)) {
+                   printf("%s not present\n", m->name);
+                   return 0;
+               }
+               printf("using %s\n", m->name);
+               goto ok;
+           }
+       }
+       printf("unknown connector\n");
+       return 0;
+
+ok:
+       /*
+       * Read the station address from the eeprom
+       */
+       p = (u_short *) eth_myaddr;
+       for (i = 0; i < 3; i++) {
+         u_short help;
+         GO_WINDOW(0);
+         help = ep_get_e(i);
+         p[i] = ((help & 0xff) << 8) | ((help & 0xff00) >> 8);
+         GO_WINDOW(2);
+         outw(BASE + EP_W2_ADDR_0 + (i * 2), help);
+       }
+       for (i = 0; i < 6; i++)
+               myadr[i] = eth_myaddr[i];
+
+       epreset();
+
+#ifdef _STANDALONE
+       strncpy(bi_netif.ifname, "ep", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_ISA;
+       bi_netif.addr.iobase = eth_base;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+
+       return 1;
+}
+
+static int
+send_ID_sequence(int port)
+{
+       int cx, al;
+
+       for (al = 0xff, cx = 0; cx < 255; cx++) {
+               outb(port, al);
+               al <<= 1;
+               if (al & 0x100)
+                       al ^= 0xcf;
+       }
+       return 1;
+}
+
+/*
+ * We get eeprom data from the id_port given an offset into the eeprom.
+ * Basically; after the ID_sequence is sent to all of the cards; they enter
+ * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
+ * the eeprom data.  We then read the port 16 times and with every read; the
+ * cards check for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
+ * compares the data on the bus; if there is a difference then that card goes
+ * into ID_WAIT state again). In the meantime; one bit of data is returned in
+ * the AX register which is conveniently returned to us by inb().  Hence; we
+ * read 16 times getting one bit of data with each read.
+ */
+static int
+get_eeprom_data(int id_port, int offset)
+{
+       int i, data = 0;
+       outb(id_port, 0x80 + offset);
+       delay(1000);
+       for (i = 0; i < 16; i++)
+               data = (data << 1) | (inw(id_port) & 1);
+       return data;
+}
diff --git a/sys/arch/i386/stand/lib/netif/3c509.h b/sys/arch/i386/stand/lib/netif/3c509.h
new file mode 100644 (file)
index 0000000..eb6ca4a
--- /dev/null
@@ -0,0 +1,393 @@
+/*     $NetBSD: 3c509.h,v 1.6 2006/11/24 22:52:16 wiz Exp $    */
+
+/*
+ * Copyright (c) 1993 Herb Peyerl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by:
+ *
+ October 2, 1994
+
+ Modified by: Andres Vega Garcia
+
+ INRIA - Sophia Antipolis, France
+ e-mail: avega@sophia.inria.fr
+ finger: avega@pax.inria.fr
+
+ */
+
+/*
+ * Ethernet software status per interface.
+ */
+/*
+ * Some global constants
+ */
+#define ETHER_MIN_LEN       64
+#define ETHER_MAX_LEN     1518
+#define ETHER_ADDR_LEN       6
+
+#define TX_INIT_RATE         16
+#define TX_INIT_MAX_RATE     64
+#define RX_INIT_LATENCY      64
+#define RX_INIT_EARLY_THRESH 64
+#define MIN_RX_EARLY_THRESHF   16 /* not less than ether_header */
+#define MIN_RX_EARLY_THRESHL   4
+
+#define EEPROMSIZE      0x40
+#define MAX_EEPROMBUSY  1000
+#define EP_LAST_TAG     0xd7
+#define EP_MAX_BOARDS   16
+#define EP_ID_PORT      0x100
+
+/*
+ * some macros to acces long named fields
+ */
+#define IS_BASE (eth_base)
+#define BASE   (eth_base)
+
+/*
+ * Commands to read/write EEPROM through EEPROM command register (Window 0,
+ * Offset 0xa)
+ */
+#define EEPROM_CMD_RD    0x0080        /* Read:  Address required (5 bits) */
+#define EEPROM_CMD_WR    0x0040        /* Write: Address required (5 bits) */
+#define EEPROM_CMD_ERASE 0x00c0        /* Erase: Address required (5 bits) */
+#define EEPROM_CMD_EWEN  0x0030        /* Erase/Write Enable: No data required */
+
+#define EEPROM_BUSY            (1<<15)
+#define EEPROM_TST_MODE                (1<<14)
+
+/*
+ * Some short functions, worth to let them be a macro
+ */
+#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY)
+#define GO_WINDOW(x)      outw(BASE+EP_COMMAND, WINDOW_SELECT|(x))
+
+/**************************************************************************
+ *                                                                       *
+ * These define the EEPROM data structure.  They are used in the probe
+ * function to verify the existence of the adapter after having sent
+ * the ID_Sequence.
+ *
+ * There are others but only the ones we use are defined here.
+ *
+ **************************************************************************/
+
+#define EEPROM_NODE_ADDR_0     0x0     /* Word */
+#define EEPROM_NODE_ADDR_1     0x1     /* Word */
+#define EEPROM_NODE_ADDR_2     0x2     /* Word */
+#define EEPROM_PROD_ID         0x3     /* 0x9[0-f]50 */
+#define EEPROM_MFG_ID          0x7     /* 0x6d50 */
+#define EEPROM_ADDR_CFG                0x8     /* Base addr */
+#define EEPROM_RESOURCE_CFG    0x9     /* IRQ. Bits 12-15 */
+
+/**************************************************************************
+ *                                                                               *
+ * These are the registers for the 3Com 3c509 and their bit patterns when *
+ * applicable.  They have been taken out of the "EtherLink III Parallel   *
+ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
+ * from 3com.                                                            *
+ *                                                                               *
+ **************************************************************************/
+
+#define EP_COMMAND             0x0e    /* Write. BASE+0x0e is always a
+                                        * command reg. */
+#define EP_STATUS              0x0e    /* Read. BASE+0x0e is always status
+                                        * reg. */
+#define EP_WINDOW              0x0f    /* Read. BASE+0x0f is always window
+                                        * reg. */
+/*
+ * Window 0 registers. Setup.
+ */
+/* Write */
+#define EP_W0_EEPROM_DATA      0x0c
+#define EP_W0_EEPROM_COMMAND   0x0a
+#define EP_W0_RESOURCE_CFG     0x08
+#define EP_W0_ADDRESS_CFG      0x06
+#define EP_W0_CONFIG_CTRL      0x04
+/* Read */
+#define EP_W0_PRODUCT_ID       0x02
+#define EP_W0_MFG_ID           0x00
+
+/*
+ * Window 1 registers. Operating Set.
+ */
+/* Write */
+#define EP_W1_TX_PIO_WR_2      0x02
+#define EP_W1_TX_PIO_WR_1      0x00
+/* Read */
+#define EP_W1_FREE_TX          0x0c
+#define EP_W1_TX_STATUS                0x0b    /* byte */
+#define EP_W1_TIMER            0x0a    /* byte */
+#define EP_W1_RX_STATUS                0x08
+#define EP_W1_RX_PIO_RD_2      0x02
+#define EP_W1_RX_PIO_RD_1      0x00
+
+/*
+ * Window 2 registers. Station Address Setup/Read
+ */
+/* Read/Write */
+#define EP_W2_ADDR_5           0x05
+#define EP_W2_ADDR_4           0x04
+#define EP_W2_ADDR_3           0x03
+#define EP_W2_ADDR_2           0x02
+#define EP_W2_ADDR_1           0x01
+#define EP_W2_ADDR_0           0x00
+
+/*
+ * Window 3 registers.  FIFO Management.
+ */
+/* Read */
+#define EP_W3_FREE_TX          0x0c
+#define EP_W3_FREE_RX          0x0a
+
+/*
+ * Window 4 registers. Diagnostics.
+ */
+/* Read/Write */
+#define EP_W4_MEDIA_TYPE       0x0a
+#define EP_W4_CTRLR_STATUS     0x08
+#define EP_W4_NET_DIAG         0x06
+#define EP_W4_FIFO_DIAG                0x04
+#define EP_W4_HOST_DIAG                0x02
+#define EP_W4_TX_DIAG          0x00
+
+/*
+ * Window 5 Registers.  Results and Internal status.
+ */
+/* Read */
+#define EP_W5_READ_0_MASK      0x0c
+#define EP_W5_INTR_MASK                0x0a
+#define EP_W5_RX_FILTER                0x08
+#define EP_W5_RX_EARLY_THRESH  0x06
+#define EP_W5_TX_AVAIL_THRESH  0x02
+#define EP_W5_TX_START_THRESH  0x00
+
+/*
+ * Window 6 registers. Statistics.
+ */
+/* Read/Write */
+#define TX_TOTAL_OK            0x0c
+#define RX_TOTAL_OK            0x0a
+#define TX_DEFERRALS           0x08
+#define RX_FRAMES_OK           0x07
+#define TX_FRAMES_OK           0x06
+#define RX_OVERRUNS            0x05
+#define TX_COLLISIONS          0x04
+#define TX_AFTER_1_COLLISION   0x03
+#define TX_AFTER_X_COLLISIONS  0x02
+#define TX_NO_SQE              0x01
+#define TX_CD_LOST             0x00
+
+/****************************************
+ *
+ * Register definitions.
+ *
+ ****************************************/
+
+/*
+ * Command register. All windows.
+ *
+ * 16 bit register.
+ *     15-11:  5-bit code for command to be executed.
+ *     10-0:   11-bit arg if any. For commands with no args;
+ *           this can be set to anything.
+ */
+#define GLOBAL_RESET           (u_short) 0x0000        /* Wait at least 1ms
+                                                        * after issuing */
+#define WINDOW_SELECT          (u_short) (0x1<<11)
+#define START_TRANSCEIVER      (u_short) (0x2<<11)     /* Read ADDR_CFG reg to
+                                                        * determine whether
+                                                        * this is needed. If
+                                                        * so; wait 800 uSec
+                                                        * before using trans-
+                                                        * ceiver. */
+#define RX_DISABLE             (u_short) (0x3<<11)     /* state disabled on
+                                                        * power-up */
+#define RX_ENABLE              (u_short) (0x4<<11)
+#define RX_RESET               (u_short) (0x5<<11)
+#define RX_DISCARD_TOP_PACK    (u_short) (0x8<<11)
+#define TX_ENABLE              (u_short) (0x9<<11)
+#define TX_DISABLE             (u_short) (0xa<<11)
+#define TX_RESET               (u_short) (0xb<<11)
+#define REQ_INTR               (u_short) (0xc<<11)
+#define SET_INTR_MASK          (u_short) (0xe<<11)
+#define SET_RD_0_MASK          (u_short) (0xf<<11)
+#define SET_RX_FILTER          (u_short) (0x10<<11)
+#define FIL_INDIVIDUAL (u_short) (0x1)
+#define FIL_GROUP              (u_short) (0x2)
+#define FIL_BRDCST     (u_short) (0x4)
+#define FIL_ALL                (u_short) (0x8)
+#define SET_RX_EARLY_THRESH    (u_short) (0x11<<11)
+#define SET_TX_AVAIL_THRESH    (u_short) (0x12<<11)
+#define SET_TX_START_THRESH    (u_short) (0x13<<11)
+#define STATS_ENABLE           (u_short) (0x15<<11)
+#define STATS_DISABLE          (u_short) (0x16<<11)
+#define STOP_TRANSCEIVER       (u_short) (0x17<<11)
+/*
+ * The following C_* acknowledge the various interrupts. Some of them don't
+ * do anything.  See the manual.
+ */
+#define ACK_INTR               (u_short) (0x6800)
+#define C_INTR_LATCH   (u_short) (ACK_INTR|0x1)
+#define C_CARD_FAILURE (u_short) (ACK_INTR|0x2)
+#define C_TX_COMPLETE  (u_short) (ACK_INTR|0x4)
+#define C_TX_AVAIL     (u_short) (ACK_INTR|0x8)
+#define C_RX_COMPLETE  (u_short) (ACK_INTR|0x10)
+#define C_RX_EARLY     (u_short) (ACK_INTR|0x20)
+#define C_INT_RQD              (u_short) (ACK_INTR|0x40)
+#define C_UPD_STATS    (u_short) (ACK_INTR|0x80)
+
+/*
+ * Status register. All windows.
+ *
+ *     15-13:  Window number(0-7).
+ *     12:     Command_in_progress.
+ *     11:     reserved.
+ *     10:     reserved.
+ *     9:      reserved.
+ *     8:      reserved.
+ *     7:      Update Statistics.
+ *     6:      Interrupt Requested.
+ *     5:      RX Early.
+ *     4:      RX Complete.
+ *     3:      TX Available.
+ *     2:      TX Complete.
+ *     1:      Adapter Failure.
+ *     0:      Interrupt Latch.
+ */
+#define S_INTR_LATCH           (u_short) (0x1)
+#define S_CARD_FAILURE         (u_short) (0x2)
+#define S_TX_COMPLETE          (u_short) (0x4)
+#define S_TX_AVAIL             (u_short) (0x8)
+#define S_RX_COMPLETE          (u_short) (0x10)
+#define S_RX_EARLY             (u_short) (0x20)
+#define S_INT_RQD              (u_short) (0x40)
+#define S_UPD_STATS            (u_short) (0x80)
+#define S_5_INTS                (S_CARD_FAILURE|S_TX_COMPLETE|\
+                                S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
+#define S_COMMAND_IN_PROGRESS  (u_short) (0x1000)
+
+/*
+ * FIFO Registers.
+ * RX Status. Window 1/Port 08
+ *
+ *     15:     Incomplete or FIFO empty.
+ *     14:     1: Error in RX Packet   0: Incomplete or no error.
+ *     13-11:  Type of error.
+ *           1000 = Overrun.
+ *           1011 = Run Packet Error.
+ *           1100 = Alignment Error.
+ *           1101 = CRC Error.
+ *           1001 = Oversize Packet Error (>1514 bytes)
+ *           0010 = Dribble Bits.
+ *           (all other error codes, no errors.)
+ *
+ *     10-0:   RX Bytes (0-1514)
+ */
+#define ERR_RX_INCOMPLETE  (u_short) (0x1<<15)
+#define ERR_RX            (u_short) (0x1<<14)
+#define ERR_RX_OVERRUN            (u_short) (0x8<<11)
+#define ERR_RX_RUN_PKT    (u_short) (0xb<<11)
+#define ERR_RX_ALIGN      (u_short) (0xc<<11)
+#define ERR_RX_CRC        (u_short) (0xd<<11)
+#define ERR_RX_OVERSIZE           (u_short) (0x9<<11)
+#define ERR_RX_DRIBBLE    (u_short) (0x2<<11)
+
+/*
+ * FIFO Registers.
+ * TX Status. Window 1/Port 0B
+ *
+ *   Reports the transmit status of a completed transmission. Writing this
+ *   register pops the transmit completion stack.
+ *
+ *   Window 1/Port 0x0b.
+ *
+ *     7:      Complete
+ *     6:      Interrupt on successful transmission requested.
+ *     5:      Jabber Error (TP Only, TX Reset required. )
+ *     4:      Underrun (TX Reset required. )
+ *     3:      Maximum Collisions.
+ *     2:      TX Status Overflow.
+ *     1-0:    Undefined.
+ *
+ */
+#define TXS_COMPLETE           0x80
+#define TXS_SUCCES_INTR_REQ            0x40
+#define TXS_JABBER             0x20
+#define TXS_UNDERRUN           0x10
+#define TXS_MAX_COLLISION      0x8
+#define TXS_STATUS_OVERFLOW    0x4
+
+/*
+ * Configuration control register.
+ * Window 0/Port 04
+ */
+/* Read */
+#define IS_AUI                                 (1<<13)
+#define IS_BNC                                 (1<<12)
+#define IS_UTP                                 (1<<9)
+/* Write */
+#define ENABLE_DRQ_IRQ                 0x0001
+#define W0_P4_CMD_RESET_ADAPTER       0x4
+#define W0_P4_CMD_ENABLE_ADAPTER      0x1
+/*
+ * Media type and status.
+ * Window 4/Port 0A
+ */
+#define ENABLE_UTP                     0xc0
+#define DISABLE_UTP                    0x0
+
+/*
+ * Resource control register
+ */
+
+#define SET_IRQ(i)     ( ((i)<<12) | 0xF00) /* set IRQ i */
+
+/*
+ * Receive status register
+ */
+
+#define RX_BYTES_MASK                  (u_short) (0x07ff)
+#define RX_ERROR       0x4000
+#define RX_INCOMPLETE  0x8000
+
+
+/*
+ * Misc defines for various things.
+ */
+#define ACTIVATE_ADAPTER_TO_CONFIG     0xff /* to the id_port */
+#define MFG_ID                                 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */
+#define PROD_ID                        0x9150
+
+#define AUI                            0x1
+#define BNC                            0x2
+#define UTP                            0x4
+
+#define ETHER_ADDR_LEN                 6
+#define ETHER_MAX                      1536
+#define RX_BYTES_MASK                  (u_short) (0x07ff)
+
+ /* EISA support */
+#define EP_EISA_START                    0x1000
+#define EP_EISA_W0                       0x0c80
diff --git a/sys/arch/i386/stand/lib/netif/3c590.c b/sys/arch/i386/stand/lib/netif/3c590.c
new file mode 100644 (file)
index 0000000..44dd5da
--- /dev/null
@@ -0,0 +1,161 @@
+/*     $NetBSD: 3c590.c,v 1.15 2008/12/14 18:46:33 christos Exp $      */
+
+/* stripped down from freebsd:sys/i386/netboot/3c509.c */
+
+
+/**************************************************************************
+NETBOOT -  BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters.
+  Date: Mar 22 1995
+
+ This code is based heavily on David Greenman's if_ed.c driver and
+  Andres Vega Garcia's if_ep.c driver.
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+  This software may be used, modified, copied, distributed, and sold, in
+  both source and binary form provided that the above copyright and these
+  terms are retained. Under no circumstances are the authors responsible for
+  the proper functioning of this software, nor do the authors assume any
+  responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp
+
+***************************************************************************/
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+#include <pcivar.h>
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+#include <lib/libkern/libkern.h>
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+#include "3c509.h"
+
+#define EP_W3_INTERNAL_CONFIG  0x00    /* 32 bits */
+#define EP_W3_RESET_OPTIONS    0x08    /* 16 bits */
+
+unsigned ether_medium;
+unsigned short eth_base;
+
+extern void epreset(void);
+extern int ep_get_e(int);
+
+u_char eth_myaddr[6];
+
+static struct mtabentry {
+    int address_cfg; /* configured connector */
+    int config_bit; /* connector present */
+    char *name;
+} mediatab[] = { /* indexed by media type - etherdrv.h */
+    {3, 0x10, "BNC"},
+    {0, 0x08, "UTP"},
+    {1, 0x20, "AUI"},
+    {6, 0x40, "MII"},
+};
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+static struct btinfo_netif bi_netif;
+#endif
+
+/**************************************************************************
+ETH_PROBE - Look for an adapter
+***************************************************************************/
+int
+EtherInit(unsigned char *myadr)
+{
+       /* common variables */
+       int i, j;
+       /* variables for 3C509 */
+       u_short *p;
+       struct mtabentry *m;
+
+       /*********************************************************
+                       Search for 3Com 590 card
+       ***********************************************************/
+
+       pcihdl_t hdl;
+       int iobase;
+
+       if (pcicheck() == -1) {
+               printf("cannot access PCI\n");
+               return 0;
+       }
+
+       if (pcifinddev(0x10b7, 0x5900, &hdl) &&
+           pcifinddev(0x10b7, 0x5950, &hdl) &&
+           pcifinddev(0x10b7, 0x9000, &hdl) &&
+           pcifinddev(0x10b7, 0x9001, &hdl) &&
+           pcifinddev(0x10b7, 0x9050, &hdl)) {
+               printf("cannot find 3c59x / 3c90x\n");
+               return 0;
+       }
+
+       if (pcicfgread(&hdl, 0x10, &iobase) || !(iobase & 1)) {
+               printf("cannot map IO space\n");
+               return 0;
+       }
+       eth_base = iobase & 0xfffffffc;
+
+       /* test for presence of connectors */
+       GO_WINDOW(3);
+       i = inb(IS_BASE + EP_W3_RESET_OPTIONS);
+       j = (inw(IS_BASE + EP_W3_INTERNAL_CONFIG + 2) >> 4) & 7;
+
+       GO_WINDOW(0);
+
+       for (ether_medium = 0, m = mediatab;
+            ether_medium < sizeof(mediatab) / sizeof(mediatab[0]);
+            ether_medium++, m++) {
+               if (j == m->address_cfg) {
+                       if (!(i & m->config_bit)) {
+                               printf("%s not present\n", m->name);
+                               return 0;
+                       }
+                       printf("using %s\n", m->name);
+                       goto ok;
+               }
+       }
+       printf("unknown connector\n");
+       return 0;
+
+ ok:
+       /*
+        * Read the station address from the eeprom
+        */
+       p = (u_short *) eth_myaddr;
+       for (i = 0; i < 3; i++) {
+               u_short help;
+               GO_WINDOW(0);
+               help = ep_get_e(i);
+               p[i] = ((help & 0xff) << 8) | ((help & 0xff00) >> 8);
+               GO_WINDOW(2);
+               outw(BASE + EP_W2_ADDR_0 + (i * 2), help);
+       }
+       for (i = 0; i < 6; i++)
+               myadr[i] = eth_myaddr[i];
+
+       epreset();
+
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+       strncpy(bi_netif.ifname, "ep", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_PCI;
+       bi_netif.addr.tag = hdl;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+
+       return 1;
+}
diff --git a/sys/arch/i386/stand/lib/netif/3c90xb.c b/sys/arch/i386/stand/lib/netif/3c90xb.c
new file mode 100644 (file)
index 0000000..602d0ab
--- /dev/null
@@ -0,0 +1,449 @@
+/* $NetBSD: 3c90xb.c,v 1.14 2008/12/14 18:46:33 christos Exp $ */
+
+/*
+ * Copyright (c) 1999
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+struct mbuf; /* XXX */
+typedef int bus_dmamap_t; /* XXX */
+#include <dev/ic/elink3reg.h>
+#include <dev/ic/elinkxlreg.h>
+
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+#include <pcivar.h>
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+#include <lib/libkern/libkern.h>
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+
+#define RECVBUF_SIZE 1600 /* struct ex_upd + packet */
+
+#ifdef _STANDALONE
+
+static pcihdl_t mytag;
+static char recvbuf[RECVBUF_SIZE];
+#define RECVBUF_PHYS vtophys(recvbuf)
+#define RECVBUF_VIRT ((void *)recvbuf)
+static struct ex_dpd sndbuf;
+#define SNDBUF_PHYS vtophys(&sndbuf)
+#define SNDBUF_VIRT ((void *)&sndbuf)
+
+#else /* !standalone, userspace testing environment */
+
+#define        PCI_MODE1_ENABLE        0x80000000UL
+#define PCIBUSNO 1
+#define PCIDEVNO 4
+static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIBUSNO << 16) | (PCIDEVNO << 11);
+
+extern void *mapmem(int, int);
+void *dmamem; /* virtual */
+#define DMABASE 0x3ffd800
+#define DMASIZE 10240
+#define RECVBUF_PHYS DMABASE
+#define RECVBUF_VIRT dmamem
+#define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE)
+#define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE))
+
+#endif /* _STANDALONE */
+
+
+#define CSR_READ_1(reg) inb(iobase + (reg))
+#define CSR_READ_2(reg) inw(iobase + (reg))
+#define CSR_READ_4(reg) inl(iobase + (reg))
+#define CSR_WRITE_1(reg, val) outb(iobase + (reg), val)
+#define CSR_WRITE_2(reg, val) outw(iobase + (reg), val)
+#define CSR_WRITE_4(reg, val) outl(iobase + (reg), val)
+
+#undef GO_WINDOW
+#define GO_WINDOW(x) CSR_WRITE_2(ELINK_COMMAND, WINDOW_SELECT | x)
+
+static int iobase;
+static u_char myethaddr[6];
+unsigned ether_medium;
+
+static struct {
+       int did;
+       int mii;
+} excards[] = {
+       {0x9005, 0}, /* 3c900b Combo */
+       {0x9055, 1}, /* 3c905b TP */
+       {0x9058, 0}, /* 3c905b Combo */
+       {-1}
+}, *excard;
+
+static struct mtabentry {
+       int address_cfg; /* configured connector */
+       int config_bit; /* connector present */
+       char *name;
+} mediatab[] = { /* indexed by media type - etherdrv.h */
+       {ELINKMEDIA_10BASE_2, ELINK_PCI_BNC, "BNC"},
+       {ELINKMEDIA_10BASE_T, ELINK_PCI_10BASE_T, "UTP"},
+       {ELINKMEDIA_AUI, ELINK_PCI_AUI, "AUI"},
+       {ELINKMEDIA_MII, ELINK_PCI_100BASE_MII, "MII"},
+       {ELINKMEDIA_100BASE_TX, ELINK_PCI_100BASE_TX, "100TX"},
+};
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+static struct btinfo_netif bi_netif;
+#endif
+
+#define ex_waitcmd() \
+       do { \
+               while (CSR_READ_2(ELINK_STATUS) & COMMAND_IN_PROGRESS) \
+                       continue; \
+       } while (0)
+
+void ex_reset(void);
+uint16_t ex_read_eeprom(int);
+static int ex_eeprom_busy(void);
+void ex_init(void);
+void ex_set_media(void);
+
+void
+ex_reset(void)
+{
+       CSR_WRITE_2(ELINK_COMMAND, GLOBAL_RESET);
+       delay(100000);
+       ex_waitcmd();
+}
+
+/*
+ * Read EEPROM data.
+ * XXX what to do if EEPROM doesn't unbusy?
+ */
+uint16_t
+ex_read_eeprom(int offset)
+{
+       uint16_t data = 0;
+
+       GO_WINDOW(0);
+       if (ex_eeprom_busy())
+               goto out;
+       CSR_WRITE_1(ELINK_W0_EEPROM_COMMAND, READ_EEPROM | (offset & 0x3f));
+       if (ex_eeprom_busy())
+               goto out;
+       data = CSR_READ_2(ELINK_W0_EEPROM_DATA);
+out:
+       return data;
+}
+
+static int
+ex_eeprom_busy(void)
+{
+       int i = 100;
+
+       while (i--) {
+               if (!(CSR_READ_2(ELINK_W0_EEPROM_COMMAND) & EEPROM_BUSY))
+                       return 0;
+               delay(100);
+       }
+       printf("\nex: eeprom stays busy.\n");
+       return 1;
+}
+
+/*
+ * Bring device up.
+ */
+void
+ex_init(void)
+{
+       int i;
+
+       ex_waitcmd();
+       EtherStop();
+
+       /*
+        * Set the station address and clear the station mask. The latter
+        * is needed for 90x cards, 0 is the default for 90xB cards.
+        */
+       GO_WINDOW(2);
+       for (i = 0; i < 6; i++) {
+               CSR_WRITE_1(ELINK_W2_ADDR_0 + i,
+                   myethaddr[i]);
+               CSR_WRITE_1(ELINK_W2_RECVMASK_0 + i, 0);
+       }
+
+       GO_WINDOW(3);
+
+       CSR_WRITE_2(ELINK_COMMAND, RX_RESET);
+       ex_waitcmd();
+       CSR_WRITE_2(ELINK_COMMAND, TX_RESET);
+       ex_waitcmd();
+
+       CSR_WRITE_2(ELINK_COMMAND, SET_INTR_MASK | 0); /* disable */
+       CSR_WRITE_2(ELINK_COMMAND, ACK_INTR | 0xff);
+
+       ex_set_media();
+
+       CSR_WRITE_2(ELINK_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST);
+
+       CSR_WRITE_4(ELINK_DNLISTPTR, 0);
+       CSR_WRITE_2(ELINK_COMMAND, TX_ENABLE);
+
+       CSR_WRITE_4(ELINK_UPLISTPTR, RECVBUF_PHYS);
+       CSR_WRITE_2(ELINK_COMMAND, RX_ENABLE);
+       CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL);
+
+       GO_WINDOW(1);
+}
+
+void
+ex_set_media(void)
+{
+       int config0, config1;
+
+       CSR_WRITE_2(ELINK_W3_MAC_CONTROL, 0);
+
+       if (ether_medium == ETHERMEDIUM_MII)
+               goto setcfg;
+
+       GO_WINDOW(4);
+       CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, 0);
+       CSR_WRITE_2(ELINK_COMMAND, STOP_TRANSCEIVER);
+       delay(800);
+
+       switch (ether_medium) {
+       case ETHERMEDIUM_UTP:
+               CSR_WRITE_2(ELINK_W4_MEDIA_TYPE,
+                           JABBER_GUARD_ENABLE | LINKBEAT_ENABLE);
+               break;
+       case ETHERMEDIUM_BNC:
+               CSR_WRITE_2(ELINK_COMMAND, START_TRANSCEIVER);
+               delay(800);
+               break;
+       case ETHERMEDIUM_AUI:
+               CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, SQE_ENABLE);
+               delay(800);
+               break;
+       case ETHERMEDIUM_100TX:
+               CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, LINKBEAT_ENABLE);
+               break;
+       }
+
+setcfg:
+       GO_WINDOW(3);
+
+       config0 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG);
+       config1 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2);
+
+       config1 = config1 & ~CONFIG_MEDIAMASK;
+       config1 |= (mediatab[ether_medium].address_cfg
+                   << CONFIG_MEDIAMASK_SHIFT);
+
+       CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG, config0);
+       CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG + 2, config1);
+}
+
+static void
+ex_probemedia(void)
+{
+       int i, j;
+       struct mtabentry *m;
+
+       /* test for presence of connectors */
+       GO_WINDOW(3);
+       i = CSR_READ_1(ELINK_W3_RESET_OPTIONS);
+       j = (CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2) & CONFIG_MEDIAMASK)
+               >> CONFIG_MEDIAMASK_SHIFT;
+       GO_WINDOW(0);
+
+       for (ether_medium = 0, m = mediatab;
+            ether_medium < sizeof(mediatab) / sizeof(mediatab[0]);
+            ether_medium++, m++) {
+               if (j == m->address_cfg) {
+                       if (!(i & m->config_bit)) {
+                               printf("%s not present\n", m->name);
+                               goto bad;
+                       }
+                       printf("using %s\n", m->name);
+                       return;
+               }
+       }
+       printf("unknown connector\n");
+bad:
+       ether_medium = -1;
+}
+
+int
+EtherInit(unsigned char *myadr)
+{
+       uint32_t pcicsr;
+       uint16_t val;
+       volatile struct ex_upd *upd;
+#ifndef _STANDALONE
+       uint32_t id;
+#endif
+
+       if (pcicheck()) {
+               printf("pcicheck failed\n");
+               return 0;
+       }
+#ifndef _STANDALONE
+       pcicfgread(&mytag, 0, &id);
+#endif
+       for (excard = &excards[0]; excard->did != -1; excard++) {
+#ifdef _STANDALONE
+               if (pcifinddev(0x10b7, excard->did, &mytag) == 0)
+                       goto found;
+#else
+               if (id == (0x10b7 | (excard->did << 16)))
+                       goto found;
+#endif
+       }
+       printf("no ex\n");
+       return 0;
+
+found:
+       pcicfgread(&mytag, 0x10, &iobase);
+       iobase &= ~3;
+
+#ifndef _STANDALONE
+       dmamem = mapmem(DMABASE, DMASIZE);
+       if (!dmamem)
+               return 0;
+#endif
+
+       /* enable bus mastering in PCI command register */
+       if (pcicfgread(&mytag, 0x04, (int *)&pcicsr)
+           || pcicfgwrite(&mytag, 0x04, pcicsr | 4)) {
+               printf("cannot enable DMA\n");
+               return 0;
+       }
+
+       ex_reset();
+
+       if (excard->mii)
+               ether_medium = ETHERMEDIUM_MII;
+       else {
+               ex_probemedia();
+               if (ether_medium < 0)
+                       return 0;
+       }
+
+       val = ex_read_eeprom(EEPROM_OEM_ADDR0);
+       myethaddr[0] = val >> 8;
+       myethaddr[1] = val & 0xff;
+       val = ex_read_eeprom(EEPROM_OEM_ADDR1);
+       myethaddr[2] = val >> 8;
+       myethaddr[3] = val & 0xff;
+       val = ex_read_eeprom(EEPROM_OEM_ADDR2);
+       myethaddr[4] = val >> 8;
+       myethaddr[5] = val & 0xff;
+       memcpy(myadr, myethaddr, 6);
+
+       upd = RECVBUF_VIRT;
+       upd->upd_nextptr = RECVBUF_PHYS;
+       upd->upd_pktstatus = 1500;
+       upd->upd_frags[0].fr_addr = RECVBUF_PHYS + 100;
+       upd->upd_frags[0].fr_len = 1500 | EX_FR_LAST;
+
+       ex_init();
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+       strncpy(bi_netif.ifname, "ex", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_PCI;
+       bi_netif.addr.tag = mytag;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+
+       return 1;
+}
+
+void
+EtherStop(void)
+{
+       /*
+        * Issue software reset
+        */
+       CSR_WRITE_2(ELINK_COMMAND, RX_DISABLE);
+       CSR_WRITE_2(ELINK_COMMAND, TX_DISABLE);
+        CSR_WRITE_2(ELINK_COMMAND, STOP_TRANSCEIVER);
+       CSR_WRITE_2(ELINK_COMMAND, INTR_LATCH);
+}
+
+int
+EtherSend(char *pkt, int len)
+{
+       volatile struct ex_dpd *dpd;
+       int i;
+
+       dpd = SNDBUF_VIRT;
+
+       dpd->dpd_nextptr = 0;
+       dpd->dpd_fsh = len;
+#ifdef _STANDALONE
+       dpd->dpd_frags[0].fr_addr = vtophys(pkt);
+#else
+       memcpy(SNDBUF_VIRT + 100, pkt, len);
+       dpd->dpd_frags[0].fr_addr = SNDBUF_PHYS + 100;
+#endif
+       dpd->dpd_frags[0].fr_len = len | EX_FR_LAST;
+
+       CSR_WRITE_4(ELINK_DNLISTPTR, SNDBUF_PHYS);
+       CSR_WRITE_2(ELINK_COMMAND, ELINK_DNUNSTALL);
+
+       i = 10000;
+       while (!(dpd->dpd_fsh & 0x00010000)) {
+               if (--i < 0) {
+                       printf("3c90xb: send timeout\n");
+                       return -1;
+               }
+               delay(1);
+       }
+
+       return len;
+}
+
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       volatile struct ex_upd *upd;
+       int len;
+
+       upd = RECVBUF_VIRT;
+
+       if (!(upd->upd_pktstatus & ~EX_UPD_PKTLENMASK))
+               return 0;
+
+       len = upd->upd_pktstatus & EX_UPD_PKTLENMASK;
+       if (len > maxlen)
+               len = 0;
+       else
+               memcpy(pkt, RECVBUF_VIRT + 100, len);
+
+       upd->upd_pktstatus = 1500;
+       CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL);
+
+       return len;
+}
diff --git a/sys/arch/i386/stand/lib/netif/Makefile.inc b/sys/arch/i386/stand/lib/netif/Makefile.inc
new file mode 100644 (file)
index 0000000..d7f0b35
--- /dev/null
@@ -0,0 +1,36 @@
+##     $NetBSD: Makefile.inc,v 1.6 2002/02/17 20:03:11 thorpej Exp $
+
+SRCS+= netif_small.c
+
+.if (${USE_NETIF} == "3c509")
+SRCS+= 3c509.c elink3.c
+.endif
+
+.if (${USE_NETIF} == "3c590")
+SRCS+= 3c590.c elink3.c
+.endif
+
+.if (${USE_NETIF} == "wd80x3")
+SRCS+= wd80x3.c dp8390.c
+.endif
+
+.if (${USE_NETIF} == "pcnet_pci")
+SRCS+= pcnet_pci.c am7990.c
+.endif
+
+.if (${USE_NETIF} == "pcnet_isapnp")
+SRCS+= pcnet_isapnp.c am7990.c
+.endif
+
+.if (${USE_NETIF} == "i82557")
+SRCS+= i82557.c
+.endif
+
+.if (${USE_NETIF} == "3c90xb")
+SRCS+= 3c90xb.c
+.endif
+
+.if (${USE_NETIF} == "ne2000_isa")
+SRCS+= ne.c dp8390.c
+CPPFLAGS+= -DSUPPORT_NE2000
+.endif
diff --git a/sys/arch/i386/stand/lib/netif/am7990.c b/sys/arch/i386/stand/lib/netif/am7990.c
new file mode 100644 (file)
index 0000000..9d9eea8
--- /dev/null
@@ -0,0 +1,280 @@
+/*     $NetBSD: am7990.c,v 1.7 2008/12/14 18:46:33 christos Exp $      */
+
+/* mostly from netbsd:sys/arch/i386/netboot/ne2100.c
+ memory allocation now 1 chunk, added deallocation
+ receive function changed - don't use irq
+ */
+
+/*
+ * source in this file came from
+ * the Mach ethernet boot written by Leendert van Doorn.
+ *
+ * A very simple network driver for NE2100 boards that polls.
+ *
+ * Copyright (c) 1992 by Leendert van Doorn
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+
+#include "etherdrv.h"
+#include "lance.h"
+
+extern u_char eth_myaddr[6];
+
+extern int lance_rap, lance_rdp;
+
+static void *dmamem;
+
+#define LA(adr) vtophys(adr)
+
+/* Lance register offsets */
+#define LA_CSR          lance_rdp
+#define LA_CSR1         lance_rdp
+#define LA_CSR2         lance_rdp
+#define LA_CSR3         lance_rdp
+#define LA_RAP          lance_rap
+
+/*
+ * Some driver specific constants.
+ * Take care when tuning, this program only has 32 Kb
+ */
+#define        LANCEBUFSIZE    1518            /* plus 4 CRC bytes */
+#define        MAXLOOP         1000000L        /* arbitrary retry limit */
+#define        LOG2NRCVRING    2               /* log2(NRCVRING) */
+#define        NRCVRING        (1 << LOG2NRCVRING)
+
+static int next_rmd;                   /* next receive element */
+static initblock_t *initblock;         /* initialization block */
+static tmde_t *tmd;                    /* transmit ring */
+static rmde_t *rmd;                    /* receive ring */
+static char rbuffer[NRCVRING][LANCEBUFSIZE]; /* receive buffers */
+
+/*
+ * Stop ethernet board
+ */
+void
+am7990_stop(void)
+{
+       long l;
+
+       /* stop chip and disable DMA access */
+       outw(LA_RAP, RDP_CSR0);
+       outw(LA_CSR, CSR_STOP);
+       for (l = 0; (inw(LA_CSR) & CSR_STOP) == 0; l++) {
+               if (l >= MAXLOOP) {
+                       printf("Lance failed to stop\n");
+                       return;
+               }
+       }
+}
+
+/*
+ * Reset ethernet board
+ */
+void
+am7990_init(void)
+{
+       long l;
+       u_long addr;
+       int i;
+
+       /* initblock, tmd, and rmd should be 8 byte aligned;
+          sizes of initblock_t and tmde_t are multiples of 8 */
+       dmamem = alloc(sizeof(initblock_t) +
+           sizeof(tmde_t) + NRCVRING * sizeof(rmde_t) + 4);
+       /* +4 is ok because alloc()'s result is 4-byte aligned! */
+
+       initblock = (initblock_t *)(((unsigned long)dmamem + 4) & -8);
+       tmd = (tmde_t *)(initblock + 1);
+       rmd = (rmde_t *)(tmd + 1);
+
+       /* stop the chip, and make sure it did */
+       am7990_stop();
+
+       /* fill lance initialization block */
+       memset(initblock, 0, sizeof(initblock_t));
+
+       /* set my ethernet address */
+       for (i = 0; i < 6; i++)
+               initblock->ib_padr[i] = eth_myaddr[i];
+
+       /* receive ring pointer */
+       addr = LA(rmd);
+       initblock->ib_rdralow = (u_short)addr;
+       initblock->ib_rdrahigh = (u_char)(addr >> 16);
+       initblock->ib_rlen = LOG2NRCVRING << 5;
+
+       /* transmit ring with one element */
+       addr = LA(tmd);
+       initblock->ib_tdralow = (u_short)addr;
+       initblock->ib_tdrahigh = (u_char)(addr >> 16);
+       initblock->ib_tlen = 0 << 5;
+
+       /* setup the receive ring entries */
+       for (next_rmd = 0, i = 0; i < NRCVRING; i++) {
+               addr = LA(&rbuffer[i]);
+               rmd[i].rmd_ladr = (u_short)addr;
+               rmd[i].rmd_hadr = (u_char)(addr >> 16);
+               rmd[i].rmd_mcnt = 0;
+               rmd[i].rmd_bcnt = -LANCEBUFSIZE;
+               rmd[i].rmd_flags = RMD_OWN;
+       }
+
+       /* zero transmit ring */
+       memset(tmd, 0, sizeof(tmde_t));
+
+       /* give lance the init block */
+       addr = LA(initblock);
+       outw(LA_RAP, RDP_CSR1);
+       outw(LA_CSR1, (u_short)addr);
+       outw(LA_RAP, RDP_CSR2);
+       outw(LA_CSR2, (char)(addr >> 16));
+       outw(LA_RAP, RDP_CSR3);
+       outw(LA_CSR3, 0);
+
+       /* and initialize it */
+       outw(LA_RAP, RDP_CSR0);
+       outw(LA_CSR, CSR_INIT|CSR_STRT);
+
+       /* wait for the lance to complete initialization and fire it up */
+       for (l = 0; (inw(LA_CSR) & CSR_IDON) == 0; l++) {
+               if (l >= MAXLOOP) {
+                       printf("Lance failed to initialize\n");
+                       break;
+               }
+       }
+       for (l = 0; (inw(LA_CSR)&(CSR_TXON|CSR_RXON)) != (CSR_TXON|CSR_RXON); l++) {
+               if (l >= MAXLOOP) {
+                       printf("Lance not started\n");
+                       break;
+               }
+       }
+}
+
+/*
+ * Stop ethernet board and free ressources
+ */
+void
+EtherStop(void)
+{
+       am7990_stop();
+
+       dealloc(dmamem, sizeof(initblock_t) +
+           sizeof(tmde_t) + NRCVRING * sizeof(rmde_t) + 4);
+}
+
+/*
+ * Send an ethernet packet
+ */
+int
+EtherSend(char *pkt, int len)
+{
+       long l;
+       u_long addr;
+       u_short csr;
+       int savlen = len;
+
+       if (len < 60)
+               len = 60;
+       if (len > LANCEBUFSIZE) {
+               printf("packet too long\n");
+               return -1;
+       }
+
+       /* set up transmit ring element */
+       if (tmd->tmd_flags & TMD_OWN) {
+               printf("lesend: td busy, status=%x\n", tmd->tmd_flags);
+               return -1;
+       }
+       addr = LA(pkt);
+       if (addr & 1) {
+               printf("unaligned data\n");
+               return -1;
+       }
+       tmd->tmd_ladr = (u_short)addr;
+       tmd->tmd_hadr = (u_char)(addr >> 16);
+       tmd->tmd_bcnt = -len;
+       tmd->tmd_err = 0;
+       tmd->tmd_flags = TMD_OWN|TMD_STP|TMD_ENP;
+
+       /* start transmission */
+       outw(LA_CSR, CSR_TDMD);
+
+       /* wait for interrupt and acknowledge it */
+       for (l = 0; l < MAXLOOP; l++) {
+               if ((csr = inw(LA_CSR)) & CSR_TINT) {
+                       outw(LA_CSR, CSR_TINT);
+#ifdef LEDEBUG
+                       if (tmd->tmd_flags & (TMD_ONE|TMD_MORE|TMD_ERR|TMD_DEF))
+                               printf("lesend: status=%x\n", tmd->tmd_flags);
+#endif
+                       break;
+               }
+               delay(10); /* don't poll too much on PCI, seems
+                             to disturb DMA on poor hardware */
+       }
+       return savlen;
+}
+
+/*
+ * Poll the LANCE just see if there's an Ethernet packet
+ * available. If there is, its contents is returned.
+ */
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       rmde_t *rp;
+       u_short csr;
+       int len = 0;
+
+       csr = inw(LA_CSR);
+       outw(LA_CSR, csr & (CSR_BABL | CSR_MISS | CSR_MERR | CSR_RINT));
+
+       if ((next_rmd < 0) || (next_rmd >= NRCVRING)) {
+               printf("next_rmd bad\n");
+               return 0;
+       }
+       rp = &rmd[next_rmd];
+
+       if (rp->rmd_flags & RMD_OWN)
+               return 0;
+
+       if (csr & (CSR_BABL | CSR_CERR | CSR_MISS | CSR_MERR))
+               printf("le: csr %x\n", csr);
+
+       if (rp->rmd_flags & (RMD_FRAM | RMD_OFLO | RMD_CRC | RMD_BUFF)) {
+               printf("le: rmd_flags %x\n", rp->rmd_flags);
+               goto cleanup;
+       }
+
+       if (rp->rmd_flags != (RMD_STP|RMD_ENP)) {
+               printf("le: rmd_flags %x\n", rp->rmd_flags);
+               return -1;
+       }
+
+       len = rp->rmd_mcnt - 4;
+
+       if ((len < 0) || (len >= LANCEBUFSIZE)) {
+               printf("bad pkt len\n");
+               return -1;
+       }
+
+       if (len <= maxlen)
+               memcpy(pkt, rbuffer[next_rmd], len);
+       else
+               len = 0;
+
+ cleanup:
+       /* give packet back to the lance */
+       rp->rmd_bcnt = -LANCEBUFSIZE;
+       rp->rmd_mcnt = 0;
+       rp->rmd_flags = RMD_OWN;
+       next_rmd = (next_rmd + 1) & (NRCVRING - 1);
+
+       return len;
+}
diff --git a/sys/arch/i386/stand/lib/netif/dp8390.c b/sys/arch/i386/stand/lib/netif/dp8390.c
new file mode 100644 (file)
index 0000000..754abb6
--- /dev/null
@@ -0,0 +1,362 @@
+/*     $NetBSD: dp8390.c,v 1.6 2008/12/14 18:46:33 christos Exp $      */
+
+/*
+ * Polling driver for National Semiconductor DS8390/WD83C690 based
+ * ethernet adapters.
+ *
+ * Copyright (c) 1998 Matthias Drochner.  All rights reserved.
+ *
+ * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * Copyright (C) 1993, David Greenman.  This software may be used, modified,
+ * copied, distributed, and sold, in both source and binary form provided that
+ * the above copyright and these terms are retained.  Under no circumstances is
+ * the author responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its use.
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+#include <libi386.h>
+
+#include <dev/ic/dp8390reg.h>
+#include "dp8390.h"
+#ifdef SUPPORT_NE2000
+#include "ne.h"
+#endif
+
+#include "etherdrv.h"
+
+int dp8390_iobase, dp8390_membase, dp8390_memsize;
+#if defined(SUPPORT_WD80X3) && defined(SUPPORT_SMC_ULTRA)
+int dp8390_is790;
+#endif
+uint8_t dp8390_cr_proto;
+uint8_t dp8390_dcr_reg;
+
+#define WE_IOBASE dp8390_iobase
+
+static u_short rec_page_start;
+static u_short rec_page_stop;
+static u_short next_packet;
+
+extern u_char eth_myaddr[6];
+
+#ifndef _STANDALONE
+static void *vmembase;
+extern void *mapmem(int, int);
+extern void unmapmem(void *, int);
+extern int mapio(void);
+
+static void
+bbcopy(void *src, void *dst, int len)
+{
+       char *s = (char *)src;
+       char *d = (char *)dst;
+
+       while (len--)
+               *d++ = *s++;
+}
+#endif
+
+static void dp8390_read(int, char *, u_short);
+
+#define NIC_GET(reg) inb(WE_IOBASE + reg)
+#define NIC_PUT(reg, val) outb(WE_IOBASE + reg, val)
+
+static void
+dp8390_init(void)
+{
+       int i;
+
+       /*
+        * Initialize the NIC in the exact order outlined in the NS manual.
+        * This init procedure is "mandatory"...don't change what or when
+        * things happen.
+        */
+
+       /* Set interface for page 0, remote DMA complete, stopped. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+
+       if (dp8390_dcr_reg & ED_DCR_LS) {
+               NIC_PUT(ED_P0_DCR, dp8390_dcr_reg);
+       } else {
+               /*
+                * Set FIFO threshold to 8, No auto-init Remote DMA, byte
+                * order=80x86, byte-wide DMA xfers,
+                */
+               NIC_PUT(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+       }
+
+       /* Clear remote byte count registers. */
+       NIC_PUT(ED_P0_RBCR0, 0);
+       NIC_PUT(ED_P0_RBCR1, 0);
+
+       /* Tell RCR to do nothing for now. */
+       NIC_PUT(ED_P0_RCR, ED_RCR_MON);
+
+       /* Place NIC in internal loopback mode. */
+       NIC_PUT(ED_P0_TCR, ED_TCR_LB0);
+
+       /* Set lower bits of byte addressable framing to 0. */
+       if (dp8390_is790)
+               NIC_PUT(0x09, 0);
+
+       /* Initialize receive buffer ring. */
+       NIC_PUT(ED_P0_BNRY, rec_page_start);
+       NIC_PUT(ED_P0_PSTART, rec_page_start);
+       NIC_PUT(ED_P0_PSTOP, rec_page_stop);
+
+       /*
+        * Clear all interrupts.  A '1' in each bit position clears the
+        * corresponding flag.
+        */
+       NIC_PUT(ED_P0_ISR, 0xff);
+
+       /*
+        * Disable all interrupts.
+        */
+       NIC_PUT(ED_P0_IMR, 0);
+
+       /* Program command register for page 1. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
+
+       /* Copy out our station address. */
+       for (i = 0; i < 6; ++i)
+               NIC_PUT(ED_P1_PAR0 + i, eth_myaddr[i]);
+
+       /*
+        * Set current page pointer to one page after the boundary pointer, as
+        * recommended in the National manual.
+        */
+       next_packet = rec_page_start + 1;
+       NIC_PUT(ED_P1_CURR, next_packet);
+
+       /* Program command register for page 0. */
+       NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+
+       /* directed and broadcast */
+       NIC_PUT(ED_P0_RCR, ED_RCR_AB);
+
+       /* Take interface out of loopback. */
+       NIC_PUT(ED_P0_TCR, 0);
+
+       /* Fire up the interface. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+}
+
+int
+dp8390_config(void)
+{
+#ifndef _STANDALONE
+       if (mapio()) {
+               printf("no IO access\n");
+               return -1;
+       }
+       vmembase = mapmem(dp8390_membase, dp8390_memsize);
+       if (!vmembase) {
+               printf("no memory access\n");
+               return -1;
+       }
+#endif
+
+       rec_page_start = TX_PAGE_START + ED_TXBUF_SIZE;
+       rec_page_stop = TX_PAGE_START + (dp8390_memsize >> ED_PAGE_SHIFT);
+
+       dp8390_init();
+
+       return 0;
+}
+
+void
+dp8390_stop(void)
+{
+       int n = 5000;
+
+       /* Stop everything on the interface, and select page 0 registers. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+
+       /*
+        * Wait for interface to enter stopped state, but limit # of checks to
+        * 'n' (about 5ms).  It shouldn't even take 5us on modern DS8390's, but
+        * just in case it's an old one.
+        */
+       while (((NIC_GET(ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
+               continue;
+
+#ifndef _STANDALONE
+       unmapmem(vmembase, dp8390_memsize);
+#endif
+}
+
+int
+EtherSend(char *pkt, int len)
+{
+#ifdef SUPPORT_NE2000
+       ne2000_writemem(pkt, dp8390_membase, len);
+#else
+#ifdef _STANDALONE
+       vpbcopy(pkt, (void *)dp8390_membase, len);
+#else
+       bbcopy(pkt, vmembase, len);
+#endif
+#endif
+
+       /* Set TX buffer start page. */
+       NIC_PUT(ED_P0_TPSR, TX_PAGE_START);
+
+       /* Set TX length. */
+       NIC_PUT(ED_P0_TBCR0, len < 60 ? 60 : len);
+       NIC_PUT(ED_P0_TBCR1, len >> 8);
+
+       /* Set page 0, remote DMA complete, transmit packet, and *start*. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
+
+       return len;
+}
+
+static void
+dp8390_read(int buf, char *dest, u_short len)
+{
+       u_short tmp_amount;
+
+       /* Does copy wrap to lower addr in ring buffer? */
+       if (buf + len > dp8390_membase + dp8390_memsize) {
+               tmp_amount = dp8390_membase + dp8390_memsize - buf;
+
+               /* Copy amount up to end of NIC memory. */
+#ifdef SUPPORT_NE2000
+               ne2000_readmem(buf, dest, tmp_amount);
+#else
+#ifdef _STANDALONE
+               pvbcopy((void *)buf, dest, tmp_amount);
+#else
+               bbcopy(vmembase + buf - dp8390_membase, dest, tmp_amount);
+#endif
+#endif
+
+               len -= tmp_amount;
+               buf = RX_BUFBASE + (rec_page_start << ED_PAGE_SHIFT);
+               dest += tmp_amount;
+       }
+#ifdef SUPPORT_NE2000
+       ne2000_readmem(buf, dest, len);
+#else
+#ifdef _STANDALONE
+       pvbcopy((void *)buf, dest, len);
+#else
+       bbcopy(vmembase + buf - dp8390_membase, dest, len);
+#endif
+#endif
+}
+
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       struct dp8390_ring packet_hdr;
+       int packet_ptr;
+       u_short len;
+       u_char boundary, current;
+#ifdef DP8390_OLDCHIPS
+       u_char nlen;
+#endif
+
+       if (!(NIC_GET(ED_P0_RSR) & ED_RSR_PRX))
+               return 0; /* XXX error handling */
+
+       /* Set NIC to page 1 registers to get 'current' pointer. */
+       NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
+
+       /*
+        * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
+        * it points to where new data has been buffered.  The 'CURR' (current)
+        * register points to the logical end of the ring-buffer - i.e. it
+        * points to where additional new data will be added.  We loop here
+        * until the logical beginning equals the logical end (or in other
+        * words, until the ring-buffer is empty).
+        */
+       current = NIC_GET(ED_P1_CURR);
+
+       /* Set NIC to page 0 registers to update boundary register. */
+       NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+
+       if (next_packet == current)
+               return 0;
+
+       /* Get pointer to this buffer's header structure. */
+       packet_ptr = RX_BUFBASE + (next_packet << ED_PAGE_SHIFT);
+
+       /*
+        * The byte count includes a 4 byte header that was added by
+        * the NIC.
+        */
+#ifdef SUPPORT_NE2000
+       ne2000_readmem(packet_ptr, (void *)&packet_hdr, 4);
+#else
+#ifdef _STANDALONE
+       pvbcopy((void *)packet_ptr, &packet_hdr, 4);
+#else
+       bbcopy(vmembase + packet_ptr - dp8390_membase, &packet_hdr, 4);
+#endif
+#endif
+
+       len = packet_hdr.count;
+
+#ifdef DP8390_OLDCHIPS
+       /*
+        * Try do deal with old, buggy chips that sometimes duplicate
+        * the low byte of the length into the high byte.  We do this
+        * by simply ignoring the high byte of the length and always
+        * recalculating it.
+        *
+        * NOTE: sc->next_packet is pointing at the current packet.
+        */
+       if (packet_hdr.next_packet >= next_packet)
+               nlen = (packet_hdr.next_packet - next_packet);
+       else
+               nlen = ((packet_hdr.next_packet - rec_page_start) +
+                       (rec_page_stop - next_packet));
+       --nlen;
+       if ((len & ED_PAGE_MASK) + sizeof(packet_hdr) > ED_PAGE_SIZE)
+               --nlen;
+       len = (len & ED_PAGE_MASK) | (nlen << ED_PAGE_SHIFT);
+#ifdef DIAGNOSTIC
+       if (len != packet_hdr.count) {
+               printf(IFNAME ": length does not match next packet pointer\n");
+               printf(IFNAME ": len %04x nlen %04x start %02x "
+                      "first %02x curr %02x next %02x stop %02x\n",
+                      packet_hdr.count, len,
+                      rec_page_start, next_packet, current,
+                      packet_hdr.next_packet, rec_page_stop);
+       }
+#endif
+#endif
+
+       if (packet_hdr.next_packet < rec_page_start ||
+           packet_hdr.next_packet >= rec_page_stop)
+               panic(IFNAME ": RAM corrupt");
+
+       len -= sizeof(struct dp8390_ring);
+       if (len < maxlen) {
+               /* Go get packet. */
+               dp8390_read(packet_ptr + sizeof(struct dp8390_ring),
+                           pkt, len);
+       } else
+               len = 0;
+
+       /* Update next packet pointer. */
+       next_packet = packet_hdr.next_packet;
+
+       /*
+        * Update NIC boundary pointer - being careful to keep it one
+        * buffer behind (as recommended by NS databook).
+        */
+       boundary = next_packet - 1;
+       if (boundary < rec_page_start)
+               boundary = rec_page_stop - 1;
+       NIC_PUT(ED_P0_BNRY, boundary);
+
+       return len;
+}
diff --git a/sys/arch/i386/stand/lib/netif/dp8390.h b/sys/arch/i386/stand/lib/netif/dp8390.h
new file mode 100644 (file)
index 0000000..c1d4094
--- /dev/null
@@ -0,0 +1,33 @@
+/*     $NetBSD: dp8390.h,v 1.6 2008/12/14 18:46:33 christos Exp $      */
+
+extern int dp8390_config(void);
+extern void dp8390_stop(void);
+
+extern int dp8390_iobase;
+extern int dp8390_membase;
+extern int dp8390_memsize;
+#ifdef SUPPORT_WD80X3
+#ifdef SUPPORT_SMC_ULTRA
+extern int dp8390_is790;
+#else
+#define dp8390_is790 0
+#endif
+#else
+#ifdef SUPPORT_SMC_ULTRA
+#define dp8390_is790 1
+#endif
+#endif
+
+#ifdef SUPPORT_NE2000
+#define dp8390_is790 0
+#define IFNAME "ne"
+#define RX_BUFBASE 0
+#define TX_PAGE_START (dp8390_membase >> ED_PAGE_SHIFT)
+#else
+#define IFNAME "we"
+#define RX_BUFBASE dp8390_membase
+#define TX_PAGE_START 0
+#endif
+
+extern uint8_t dp8390_cr_proto; /* values always set in CR */
+extern uint8_t dp8390_dcr_reg; /* override DCR if LS is set */
diff --git a/sys/arch/i386/stand/lib/netif/elink3.c b/sys/arch/i386/stand/lib/netif/elink3.c
new file mode 100644 (file)
index 0000000..1a115d4
--- /dev/null
@@ -0,0 +1,336 @@
+/*     $NetBSD: elink3.c,v 1.4 2008/12/14 18:46:33 christos Exp $      */
+
+/* stripped down from freebsd:sys/i386/netboot/3c509.c */
+
+/**************************************************************************
+NETBOOT -  BOOTP/TFTP Bootstrap Program
+
+Author: Martin Renters.
+  Date: Mar 22 1995
+
+ This code is based heavily on David Greenman's if_ed.c driver and
+  Andres Vega Garcia's if_ep.c driver.
+
+ Copyright (C) 1993-1994, David Greenman, Martin Renters.
+ Copyright (C) 1993-1995, Andres Vega Garcia.
+ Copyright (C) 1995, Serge Babkin.
+  This software may be used, modified, copied, distributed, and sold, in
+  both source and binary form provided that the above copyright and these
+  terms are retained. Under no circumstances are the authors responsible for
+  the proper functioning of this software, nor do the authors assume any
+  responsibility for damages incurred with its use.
+
+3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
+
+3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp
+
+***************************************************************************/
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+
+#include "etherdrv.h"
+#include "3c509.h"
+
+extern unsigned short eth_base;
+
+extern u_char eth_myaddr[6];
+
+void
+epstop(void)
+{
+
+       /* stop card */
+       outw(BASE + EP_COMMAND, RX_DISABLE);
+       outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+       while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
+
+       outw(BASE + EP_COMMAND, TX_DISABLE);
+       outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
+
+       outw(BASE + EP_COMMAND, RX_RESET);
+       outw(BASE + EP_COMMAND, TX_RESET);
+
+       outw(BASE + EP_COMMAND, C_INTR_LATCH);
+       outw(BASE + EP_COMMAND, SET_RD_0_MASK);
+       outw(BASE + EP_COMMAND, SET_INTR_MASK);
+       outw(BASE + EP_COMMAND, SET_RX_FILTER);
+}
+
+void
+EtherStop(void)
+{
+
+       epstop();
+       outw(BASE + EP_COMMAND, GLOBAL_RESET);
+       delay(100000);
+}
+
+/**************************************************************************
+ETH_RESET - Reset adapter
+***************************************************************************/
+void
+epreset(void)
+{
+       int i;
+
+       /***********************************************************
+                       Reset 3Com 509 card
+       *************************************************************/
+
+       epstop();
+
+       /*
+        * initialize card
+       */
+       while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+               continue;
+
+       GO_WINDOW(0);
+
+       /* Disable the card */
+       outw(BASE + EP_W0_CONFIG_CTRL, 0);
+
+       /* Configure IRQ to none */
+       outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0));
+
+       /* Enable the card */
+       outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
+
+       GO_WINDOW(2);
+
+       /* Reload the ether_addr. */
+       for (i = 0; i < 6; i++)
+               outb(BASE + EP_W2_ADDR_0 + i, eth_myaddr[i]);
+
+       outw(BASE + EP_COMMAND, RX_RESET);
+       outw(BASE + EP_COMMAND, TX_RESET);
+
+       /* Window 1 is operating window */
+       GO_WINDOW(1);
+       for (i = 0; i < 31; i++)
+               inb(BASE + EP_W1_TX_STATUS);
+
+       /* get rid of stray intr's */
+       outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
+
+       outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
+
+       outw(BASE + EP_COMMAND, SET_INTR_MASK);
+
+       outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
+           FIL_BRDCST);
+
+       /* configure BNC */
+       if (ether_medium == ETHERMEDIUM_BNC) {
+               outw(BASE + EP_COMMAND, START_TRANSCEIVER);
+               delay(1000);
+       }
+       /* configure UTP */
+       if (ether_medium == ETHERMEDIUM_UTP) {
+               GO_WINDOW(4);
+               outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
+               GO_WINDOW(1);
+       }
+
+       /* start tranciever and receiver */
+       outw(BASE + EP_COMMAND, RX_ENABLE);
+       outw(BASE + EP_COMMAND, TX_ENABLE);
+
+       /* set early threshold for minimal packet length */
+       outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | 64);
+
+       outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
+}
+
+/**************************************************************************
+ETH_TRANSMIT - Transmit a frame
+***************************************************************************/
+static const char padmap[] = {
+       0, 3, 2, 1};
+
+int
+EtherSend(char *pkt, int len)
+{
+       int pad;
+       int status;
+
+#ifdef EDEBUG
+       printf("{l=%d}", len);
+#endif
+
+       pad = padmap[len & 3];
+
+       /*
+       * The 3c509 automatically pads short packets to minimum ethernet length,
+       * but we drop packets that are too large. Perhaps we should truncate
+       * them instead?
+       */
+       if (len + pad > ETHER_MAX_LEN) {
+               return -1;
+       }
+
+       /* drop acknowledgements */
+       while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
+               if (status & (TXS_UNDERRUN | TXS_MAX_COLLISION |
+                       TXS_STATUS_OVERFLOW)) {
+                       outw(BASE + EP_COMMAND, TX_RESET);
+                       outw(BASE + EP_COMMAND, TX_ENABLE);
+               }
+
+               outb(BASE + EP_W1_TX_STATUS, 0x0);
+       }
+
+       while (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
+               /* no room in FIFO */
+               continue;
+       }
+
+       outw(BASE + EP_W1_TX_PIO_WR_1, len);
+       outw(BASE + EP_W1_TX_PIO_WR_1, 0x0);    /* Second dword meaningless */
+
+       /* write packet */
+       outsw(BASE + EP_W1_TX_PIO_WR_1, pkt, len / 2);
+       if (len & 1)
+               outb(BASE + EP_W1_TX_PIO_WR_1, *(pkt + len - 1));
+
+       while (pad--)
+               outb(BASE + EP_W1_TX_PIO_WR_1, 0);      /* Padding */
+
+       /* timeout after sending */
+       delay(1000);
+       return len;
+}
+
+/**************************************************************************
+ETH_POLL - Wait for a frame
+***************************************************************************/
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       /* common variables */
+       int len;
+       /* variables for 3C509 */
+       short status, cst;
+       register short rx_fifo;
+
+       cst = inw(BASE + EP_STATUS);
+
+#ifdef EDEBUG
+       if (cst & 0x1FFF)
+               printf("-%x-",cst);
+#endif
+
+       if ((cst & (S_RX_COMPLETE|S_RX_EARLY)) == 0) {
+               /* acknowledge  everything */
+               outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS));
+               outw(BASE + EP_COMMAND, C_INTR_LATCH);
+
+               return 0;
+       }
+
+       status = inw(BASE + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+       printf("*%x*",status);
+#endif
+
+       if (status & ERR_RX) {
+               outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+               return 0;
+       }
+
+       rx_fifo = status & RX_BYTES_MASK;
+       if (rx_fifo == 0)
+               return 0;
+
+       if (rx_fifo > maxlen)
+               goto zulang;
+
+       /* read packet */
+#ifdef EDEBUG
+       printf("[l=%d",rx_fifo);
+#endif
+       insw(BASE + EP_W1_RX_PIO_RD_1, pkt, rx_fifo / 2);
+       if (rx_fifo & 1)
+               pkt[rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1);
+       len = rx_fifo;
+
+       for (;;) {
+               status = inw(BASE + EP_W1_RX_STATUS);
+#ifdef EDEBUG
+               printf("*%x*",status);
+#endif
+               rx_fifo = status & RX_BYTES_MASK;
+
+               if (rx_fifo > 0) {
+                       if ((len + rx_fifo) > maxlen)
+                               goto zulang;
+
+                       insw(BASE + EP_W1_RX_PIO_RD_1, pkt + len, rx_fifo / 2);
+                       if (rx_fifo & 1)
+                               pkt[len + rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1);
+                       len += rx_fifo;
+#ifdef EDEBUG
+                       printf("+%d",rx_fifo);
+#endif
+               }
+
+               if ((status & RX_INCOMPLETE) == 0) {
+#ifdef EDEBUG
+                       printf("=%d",len);
+#endif
+                       break;
+               }
+
+               delay(1000);
+       }
+
+       /* acknowledge reception of packet */
+       outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+       while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+               continue;
+
+       return len;
+
+ zulang:
+       outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
+       while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
+               continue;
+       return 0;
+}
+
+/*************************************************************************
+       3Com 509 - specific routines
+**************************************************************************/
+
+static int
+eeprom_rdy(void)
+{
+       int i;
+
+       for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
+       if (i >= MAX_EEPROMBUSY) {
+               printf("3c509: eeprom failed to come ready.\r\n");
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * get_e: gets a 16 bits word from the EEPROM. we must have set the window
+ * before
+ */
+int
+ep_get_e(int offset)
+{
+       if (!eeprom_rdy())
+               return 0xffff;
+       outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
+       if (!eeprom_rdy())
+               return 0xffff;
+       return inw(IS_BASE + EP_W0_EEPROM_DATA);
+}
diff --git a/sys/arch/i386/stand/lib/netif/etherdrv.h b/sys/arch/i386/stand/lib/netif/etherdrv.h
new file mode 100644 (file)
index 0000000..4ef2394
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $NetBSD: etherdrv.h,v 1.9 2008/12/14 18:46:33 christos Exp $    */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+int EtherInit(unsigned char *);
+int EtherSend(char *, int);
+int EtherReceive(char *, int);
+void EtherStop(void);
+
+extern unsigned ether_medium;
+#define ETHERMEDIUM_BNC 0
+#define ETHERMEDIUM_UTP 1
+#define ETHERMEDIUM_AUI 2
+#define ETHERMEDIUM_MII 3
+#define ETHERMEDIUM_100TX 4
diff --git a/sys/arch/i386/stand/lib/netif/i82557.c b/sys/arch/i386/stand/lib/netif/i82557.c
new file mode 100644 (file)
index 0000000..6579c97
--- /dev/null
@@ -0,0 +1,492 @@
+/* $NetBSD: i82557.c,v 1.11 2008/12/14 18:46:33 christos Exp $ */
+
+/*
+ * Copyright (c) 1998, 1999
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1995, David Greenman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <dev/ic/i82557reg.h>
+
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+#include <pcivar.h>
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+#include <lib/libkern/libkern.h>
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+
+#define RECVBUF_SIZE 1600 /* struct fxp_rfa + packet */
+
+#ifdef _STANDALONE
+static pcihdl_t mytag;
+static char recvbuf[RECVBUF_SIZE];
+#define RECVBUF_PHYS vtophys(recvbuf)
+#define RECVBUF_VIRT ((void *)recvbuf)
+static union _sndbuf {
+       struct fxp_cb_config cbp;
+       struct fxp_cb_ias cb_ias;
+       struct fxp_cb_tx txp;
+} sndbuf;
+#define SNDBUF_PHYS vtophys(&sndbuf)
+#define SNDBUF_VIRT ((void *)&sndbuf)
+#else /* !standalone, userspace testing environment */
+#define        PCI_MODE1_ENABLE        0x80000000UL
+static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIDEVNO << 11);
+
+extern void *mapmem(int, int);
+void *dmamem; /* virtual */
+#define RECVBUF_PHYS DMABASE
+#define RECVBUF_VIRT dmamem
+#define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE)
+#define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE))
+#endif /* _STANDALONE */
+
+static void fxp_read_eeprom(uint16_t *, int, int);
+static inline void fxp_scb_wait(void);
+#ifdef DEBUG
+static void fxp_checkintr(char *);
+#else
+#define fxp_checkintr(x)
+#endif
+static void fxp_startreceiver(void);
+
+/*
+ * Template for default configuration parameters.
+ * See struct fxp_cb_config for the bit definitions.
+ */
+static uint8_t fxp_cb_config_template[] = {
+       0x0, 0x0,               /* cb_status */
+       0x80, 0x2,              /* cb_command */
+       0xff, 0xff, 0xff, 0xff, /* link_addr */
+       0x16,   /*  0 */
+       0x8,    /*  1 */
+       0x0,    /*  2 */
+       0x0,    /*  3 */
+       0x0,    /*  4 */
+       0x80,   /*  5 */
+       0xb2,   /*  6 */
+       0x3,    /*  7 */
+       0x1,    /*  8 */
+       0x0,    /*  9 */
+       0x26,   /* 10 */
+       0x0,    /* 11 */
+       0x60,   /* 12 */
+       0x0,    /* 13 */
+       0xf2,   /* 14 */
+       0x48,   /* 15 */
+       0x0,    /* 16 */
+       0x40,   /* 17 */
+       0xf3,   /* 18 */
+       0x0,    /* 19 */
+       0x3f,   /* 20 */
+       0x5     /* 21 */
+};
+
+static int tx_threshold = 64; /* x8, max 192 */
+
+#define CSR_READ_1(reg) inb(iobase + (reg))
+#define CSR_READ_2(reg) inw(iobase + (reg))
+#define CSR_WRITE_1(reg, val) outb(iobase + (reg), val)
+#define CSR_WRITE_2(reg, val) outw(iobase + (reg), val)
+#define CSR_WRITE_4(reg, val) outl(iobase + (reg), val)
+#define DELAY(n) delay(n)
+
+static int iobase;
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+static struct btinfo_netif bi_netif;
+#endif
+
+/*
+ * Wait for the previous command to be accepted (but not necessarily
+ * completed).
+ */
+static inline void
+fxp_scb_wait(void)
+{
+       int i = 10000;
+
+       while (CSR_READ_1(FXP_CSR_SCB_COMMAND) && --i)
+               DELAY(1);
+       if (i == 0)
+               printf("fxp: WARNING: SCB timed out!\n");
+}
+
+#ifdef DEBUG
+static void
+fxp_checkintr(char *msg)
+{
+       uint8_t statack;
+       int i = 10000;
+
+       do {
+               statack = CSR_READ_1(FXP_CSR_SCB_STATACK);
+       } while ((statack == 0) && (--i > 0));
+
+       if (statack != 0) {
+               CSR_WRITE_1(FXP_CSR_SCB_STATACK, statack);
+               printf("%s: ack'd irq %x, i=%d\n", msg, statack, i);
+       }
+}
+#endif
+
+int
+EtherInit(unsigned char *myadr)
+{
+#ifndef _STANDALONE
+       uint32_t id;
+#endif
+       volatile struct fxp_cb_config *cbp;
+       volatile struct fxp_cb_ias *cb_ias;
+       int i;
+
+       if (pcicheck()) {
+               printf("pcicheck failed\n");
+               return 0;
+       }
+#ifdef _STANDALONE
+       if (pcifinddev(0x8086, 0x1229, &mytag)) {
+               printf("no fxp\n");
+               return 0;
+       }
+#else
+       pcicfgread(&mytag, 0, &id);
+       if (id != 0x12298086) {
+               printf("no fxp\n");
+               return 0;
+       }
+#endif
+
+       pcicfgread(&mytag, FXP_PCI_IOBA, &iobase);
+       iobase &= ~3;
+
+#ifndef _STANDALONE
+       dmamem = mapmem(DMABASE, DMASIZE);
+       if (!dmamem)
+               return 0;
+#endif
+
+       fxp_read_eeprom((void *)myadr, 0, 3);
+
+       /*
+        * Initialize base of CBL and RFA memory. Loading with zero
+        * sets it up for regular linear addressing.
+        */
+       CSR_WRITE_4(FXP_CSR_SCB_GENERAL, 0);
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
+
+       fxp_scb_wait();
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
+
+       cbp = SNDBUF_VIRT;
+       /*
+        * This memcpy is kind of disgusting, but there are a bunch of must be
+        * zero and must be one bits in this structure and this is the easiest
+        * way to initialize them all to proper values.
+        */
+       memcpy((void *)cbp, fxp_cb_config_template,
+             sizeof(fxp_cb_config_template));
+
+#define prm 0
+#define phy_10Mbps_only 0
+#define all_mcasts 0
+       cbp->cb_status =        0;
+       cbp->cb_command =       FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL;
+       cbp->link_addr =        -1;     /* (no) next command */
+       cbp->byte_count =       22;     /* (22) bytes to config */
+       cbp->rx_fifo_limit =    8;      /* rx fifo threshold (32 bytes) */
+       cbp->tx_fifo_limit =    0;      /* tx fifo threshold (0 bytes) */
+       cbp->adaptive_ifs =     0;      /* (no) adaptive interframe spacing */
+       cbp->rx_dma_bytecount = 0;      /* (no) rx DMA max */
+       cbp->tx_dma_bytecount = 0;      /* (no) tx DMA max */
+       cbp->dma_mbce =         0;      /* (disable) dma max counters */
+       cbp->late_scb =         0;      /* (don't) defer SCB update */
+       cbp->tno_int_or_tco_en = 0;     /* (disable) tx not okay interrupt */
+       cbp->ci_int =           0;      /* interrupt on CU not active */
+       cbp->save_bf =          prm;    /* save bad frames */
+       cbp->disc_short_rx =    !prm;   /* discard short packets */
+       cbp->underrun_retry =   1;      /* retry mode (1) on DMA underrun */
+       cbp->mediatype =        !phy_10Mbps_only; /* interface mode */
+       cbp->nsai =             1;     /* (don't) disable source addr insert */
+       cbp->preamble_length =  2;      /* (7 byte) preamble */
+       cbp->loopback =         0;      /* (don't) loopback */
+       cbp->linear_priority =  0;      /* (normal CSMA/CD operation) */
+       cbp->linear_pri_mode =  0;      /* (wait after xmit only) */
+       cbp->interfrm_spacing = 6;      /* (96 bits of) interframe spacing */
+       cbp->promiscuous =      prm;    /* promiscuous mode */
+       cbp->bcast_disable =    0;      /* (don't) disable broadcasts */
+       cbp->crscdt =           0;      /* (CRS only) */
+       cbp->stripping =        !prm;   /* truncate rx packet to byte count */
+       cbp->padding =          1;      /* (do) pad short tx packets */
+       cbp->rcv_crc_xfer =     0;      /* (don't) xfer CRC to host */
+       cbp->force_fdx =        0;      /* (don't) force full duplex */
+       cbp->fdx_pin_en =       1;      /* (enable) FDX# pin */
+       cbp->multi_ia =         0;      /* (don't) accept multiple IAs */
+       cbp->mc_all =           all_mcasts;/* accept all multicasts */
+#undef prm
+#undef phy_10Mbps_only
+#undef all_mcasts
+
+       /*
+        * Start the config command/DMA.
+        */
+       fxp_scb_wait();
+       CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+       /* ...and wait for it to complete. */
+       i = 10000;
+       while (!(cbp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
+               DELAY(1);
+       if (i == 0)
+               printf("config timeout");
+
+       fxp_checkintr("config");
+
+       cb_ias = SNDBUF_VIRT;
+       /*
+        * Now initialize the station address. Temporarily use the TxCB
+        * memory area like we did above for the config CB.
+        */
+       cb_ias->cb_status = 0;
+       cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL;
+       cb_ias->link_addr = -1;
+       memcpy((void *)cb_ias->macaddr, myadr, 6);
+
+       /*
+        * Start the IAS (Individual Address Setup) command/DMA.
+        */
+       fxp_scb_wait();
+       /* address is still there */
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+       /* ...and wait for it to complete. */
+       i = 10000;
+       while (!(cb_ias->cb_status & FXP_CB_STATUS_C) && (--i > 0))
+               DELAY(1);
+       if (i == 0)
+               printf("ias timeout");
+
+       fxp_checkintr("ias");
+
+       fxp_startreceiver();
+
+#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD)
+       strncpy(bi_netif.ifname, "fxp", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_PCI;
+       bi_netif.addr.tag = mytag;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+
+       return 1;
+}
+
+void
+EtherStop(void)
+{
+
+       /*
+        * Issue software reset
+        */
+       CSR_WRITE_4(FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
+       DELAY(10);
+}
+
+int
+EtherSend(char *pkt, int len)
+{
+       volatile struct fxp_cb_tx *txp;
+#ifdef _STANDALONE
+       static volatile struct fxp_tbd tbd;
+#endif
+       volatile struct fxp_tbd *tbdp;
+       int i;
+
+       txp = SNDBUF_VIRT;
+#ifdef _STANDALONE
+       tbdp = &tbd;
+       txp->tbd_array_addr = vtophys((void *)&tbd);
+       tbdp->tb_addr = vtophys(pkt);
+#else
+       /* XXX assuming we send at max 400 bytes */
+       tbdp = (struct fxp_tbd *)(SNDBUF_VIRT + 440);
+       txp->tbd_array_addr = SNDBUF_PHYS + 440;
+       memcpy(SNDBUF_VIRT + 400, pkt, len);
+       tbdp->tb_addr = SNDBUF_PHYS + 400;
+#endif
+       tbdp->tb_size = len;
+       txp->tbd_number = 1;
+       txp->cb_status = 0;
+       txp->cb_command =
+           FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_EL;
+       txp->tx_threshold = tx_threshold;
+
+       txp->link_addr = -1;
+       txp->byte_count = 0;
+
+       fxp_scb_wait();
+       CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS);
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+       /* ...and wait for it to complete. */
+       i = 10000;
+       while (!(txp->cb_status & FXP_CB_STATUS_C) && (--i > 0))
+               DELAY(1);
+       if (i == 0)
+               printf("send timeout");
+
+       fxp_checkintr("send");
+
+       return len;
+}
+
+static void
+fxp_startreceiver(void)
+{
+       volatile struct fxp_rfa *rfa;
+       uint32_t v;
+
+       rfa = RECVBUF_VIRT;
+       rfa->size = RECVBUF_SIZE - sizeof(struct fxp_rfa);
+       rfa->rfa_status = 0;
+       rfa->rfa_control = FXP_RFA_CONTROL_S;
+       rfa->actual_size = 0;
+       v = RECVBUF_PHYS; /* close the "ring" */
+       memcpy((void *)&rfa->link_addr, &v, sizeof(v));
+       v = -1;
+       memcpy((void *)&rfa->rbd_addr, &v, sizeof(v));
+
+       fxp_scb_wait();
+       CSR_WRITE_4(FXP_CSR_SCB_GENERAL, RECVBUF_PHYS);
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
+}
+
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       uint8_t ruscus;
+       volatile struct fxp_rfa *rfa;
+       int len = 0;
+
+       ruscus = CSR_READ_1(FXP_CSR_SCB_RUSCUS);
+       if (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_READY)
+               return 0;
+       if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED) {
+               printf("rcv: ruscus=%x\n", ruscus);
+               return 0;
+       }
+
+       rfa = RECVBUF_VIRT;
+       if (rfa->rfa_status & FXP_RFA_STATUS_C) {
+               len = rfa->actual_size & 0x7ff;
+               if (len <= maxlen) {
+                       memcpy(pkt, (char *) rfa + RFA_SIZE, maxlen);
+#if 0
+                       printf("rfa status=%x, len=%x\n",
+                              rfa->rfa_status, len);
+#endif
+               } else
+                       len = 0;
+       }
+
+       fxp_scb_wait();
+       CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME);
+
+       return len;
+}
+
+/*
+ * Read from the serial EEPROM. Basically, you manually shift in
+ * the read opcode (one bit at a time) and then shift in the address,
+ * and then you shift out the data (all of this one bit at a time).
+ * The word size is 16 bits, so you have to provide the address for
+ * every 16 bits of data.
+ */
+static void
+fxp_read_eeprom(uint16_t *data, int offset, int words)
+{
+       uint16_t reg;
+       int i, x;
+
+       for (i = 0; i < words; i++) {
+               CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS);
+               /*
+                * Shift in read opcode.
+                */
+               for (x = 3; x > 0; x--) {
+                       if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) {
+                               reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
+                       } else {
+                               reg = FXP_EEPROM_EECS;
+                       }
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
+                           reg | FXP_EEPROM_EESK);
+                       DELAY(1);
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
+                       DELAY(1);
+               }
+               /*
+                * Shift in address.
+                */
+               for (x = 6; x > 0; x--) {
+                       if ((i + offset) & (1 << (x - 1))) {
+                               reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI;
+                       } else {
+                               reg = FXP_EEPROM_EECS;
+                       }
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
+                           reg | FXP_EEPROM_EESK);
+                       DELAY(1);
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
+                       DELAY(1);
+               }
+               reg = FXP_EEPROM_EECS;
+               data[i] = 0;
+               /*
+                * Shift out data.
+                */
+               for (x = 16; x > 0; x--) {
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL,
+                           reg | FXP_EEPROM_EESK);
+                       DELAY(1);
+                       if (CSR_READ_2(FXP_CSR_EEPROMCONTROL) &
+                           FXP_EEPROM_EEDO)
+                               data[i] |= (1 << (x - 1));
+                       CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg);
+                       DELAY(1);
+               }
+               CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, 0);
+               DELAY(1);
+       }
+}
diff --git a/sys/arch/i386/stand/lib/netif/lance.h b/sys/arch/i386/stand/lib/netif/lance.h
new file mode 100644 (file)
index 0000000..f71dd14
--- /dev/null
@@ -0,0 +1,113 @@
+/*     $NetBSD: lance.h,v 1.2 2008/12/14 18:46:33 christos Exp $       */
+
+/*
+ * source in this file came from
+ * the Mach ethernet boot written by Leendert van Doorn.
+ */
+
+/* RAP functions as a select for RDP */
+#define RDP_CSR0       0
+#define RDP_CSR1       1
+#define RDP_CSR2       2
+#define RDP_CSR3       3
+
+/* contents of csr0 */
+#define CSR_ERR                0x8000
+#define CSR_BABL       0x4000
+#define CSR_CERR       0x2000
+#define CSR_MISS       0x1000
+#define CSR_MERR       0x0800
+#define CSR_RINT       0x0400
+#define CSR_TINT       0x0200
+#define CSR_IDON       0x0100
+#define CSR_INTR       0x0080
+#define CSR_INEA       0x0040
+#define CSR_RXON       0x0020
+#define CSR_TXON       0x0010
+#define CSR_TDMD       0x0008
+#define CSR_STOP       0x0004
+#define CSR_STRT       0x0002
+#define CSR_INIT       0x0001
+
+/* csr1 contains low 16 bits of address of Initialization Block */
+
+/* csr2 contains in low byte high 8 bits of address of InitBlock */
+
+/* contents of csr3 */
+#define CSR3_BSWP      0x04    /* byte swap (for big endian) */
+#define CSR3_ACON      0x02    /* ALE control */
+#define CSR3_BCON      0x01    /* byte control */
+
+/*
+ * The initialization block
+ */
+typedef struct {
+       u_short ib_mode;        /* modebits, see below */
+       char    ib_padr[6];     /* physical 48bit Ether-address */
+       u_short ib_ladrf[4];    /* 64bit hashtable for "logical" addresses */
+       u_short ib_rdralow;     /* low 16 bits of Receiver Descr. Ring addr */
+       u_char  ib_rdrahigh;    /* high 8 bits of Receiver Descr. Ring addr */
+       u_char  ib_rlen;        /* upper 3 bits are 2log Rec. Ring Length */
+       u_short ib_tdralow;     /* low 16 bits of Transm. Descr. Ring addr */
+       u_char  ib_tdrahigh;    /* high 8 bits of Transm. Descr. Ring addr */
+       u_char  ib_tlen;        /* upper 3 bits are 2log Transm. Ring Length */
+} initblock_t;
+
+/* bits in mode */
+#define IB_PROM                0x8000
+#define IB_INTL                0x0040
+#define IB_DRTY                0x0020
+#define IB_COLL                0x0010
+#define IB_DTCR                0x0008
+#define IB_LOOP                0x0004
+#define IB_DTX         0x0002
+#define IB_DRX         0x0001
+
+/*
+ * A receive message descriptor entry
+ */
+typedef struct {
+       u_short rmd_ladr;       /* low 16 bits of bufaddr */
+       char    rmd_hadr;       /* high 8 bits of bufaddr */
+       char    rmd_flags;      /* see below */
+       short   rmd_bcnt;       /* two's complement of buffer byte count */
+       u_short rmd_mcnt;       /* message byte count */
+} rmde_t;
+
+/* bits in flags */
+#define RMD_OWN                0x80
+#define RMD_ERR                0x40
+#define RMD_FRAM       0x20
+#define RMD_OFLO       0x10
+#define RMD_CRC                0x08
+#define RMD_BUFF       0x04
+#define RMD_STP                0x02
+#define RMD_ENP                0x01
+
+/*
+ * A transmit message descriptor entry
+ */
+typedef struct {
+       u_short tmd_ladr;       /* low 16 bits of bufaddr */
+       u_char  tmd_hadr;       /* high 8 bits of bufaddr */
+       u_char  tmd_flags;      /* see below */
+       short   tmd_bcnt;       /* two's complement of buffer byte count */
+       u_short tmd_err;        /* more error bits + TDR */
+} tmde_t;
+
+/* bits in flags */
+#define TMD_OWN                0x80
+#define TMD_ERR                0x40
+#define TMD_MORE       0x10
+#define TMD_ONE                0x08
+#define TMD_DEF                0x04
+#define TMD_STP                0x02
+#define TMD_ENP                0x01
+
+/* bits in tmd_err */
+#define TMDE_BUFF      0x8000
+#define TMDE_UFLO      0x4000
+#define TMDE_LCOL      0x1000
+#define TMDE_LCAR      0x0800
+#define TMDE_RTRY      0x0400
+#define TMDE_TDR       0x003F  /* mask for TDR */
diff --git a/sys/arch/i386/stand/lib/netif/ne.c b/sys/arch/i386/stand/lib/netif/ne.c
new file mode 100644 (file)
index 0000000..d9fad5c
--- /dev/null
@@ -0,0 +1,274 @@
+/* $NetBSD: ne.c,v 1.7 2008/12/14 18:46:33 christos Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
+ * adapters.
+ *
+ * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * Copyright (C) 1993, David Greenman.  This software may be used, modified,
+ * copied, distributed, and sold, in both source and binary form provided that
+ * the above copyright and these terms are retained.  Under no circumstances is
+ * the author responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its use.
+ */
+
+/*
+ * this code is mainly obtained from /sys/dev/ic/ne2000.c .
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+#include <libi386.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+#include <dev/ic/dp8390reg.h>
+#include <dev/ic/ne2000reg.h>
+#include "dp8390.h"
+#include "ne.h"
+
+#ifndef BASEREG
+#define BASEREG 0x300
+#endif
+
+#define        NE_BASEREG BASEREG
+#define NE_ASIC_BASEREG (NE_BASEREG+NE2000_ASIC_OFFSET)
+
+#define NIC_PORT(x) (NE_BASEREG + (x))
+#define NIC_INB(x) inb(NIC_PORT(x))
+#define NIC_OUTB(x, b) outb(NIC_PORT(x), (b))
+
+#define NE_16BIT
+
+#define DELAY(x) delay(x)
+
+#define ASIC_PORT(x) (NE_ASIC_BASEREG + (x))
+#define ASIC_INB(x) inb(ASIC_PORT(x))
+#define ASIC_INW(x) inw(ASIC_PORT(x))
+#define ASIC_OUTB(x, b) outb(ASIC_PORT(x), (b))
+#define ASIC_OUTW(x, b) outw(ASIC_PORT(x), (b))
+
+u_char eth_myaddr[6];
+
+#ifdef _STANDALONE
+static struct btinfo_netif bi_netif;
+#endif
+
+int
+EtherInit(unsigned char *myadr)
+{
+       uint8_t tmp;
+       int i;
+
+       printf("ne: trying iobase=0x%x\n", NE_BASEREG);
+
+       dp8390_iobase = NE_BASEREG;
+       dp8390_membase = dp8390_memsize = 8192*2;
+       dp8390_cr_proto = ED_CR_RD2;
+       dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS
+#ifdef NE_16BIT
+       | ED_DCR_WTS
+#endif
+       ;
+
+       /* reset */
+       tmp = ASIC_INB(NE2000_ASIC_RESET);
+       DELAY(10000);
+       ASIC_OUTB(NE2000_ASIC_RESET, tmp);
+       DELAY(5000);
+
+       NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+       DELAY(5000);
+
+       tmp = NIC_INB(ED_P0_CR);
+       if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
+               (ED_CR_RD2 | ED_CR_STP)) {
+               goto out;
+       }
+
+       tmp = NIC_INB(ED_P0_ISR);
+       if ((tmp & ED_ISR_RST) != ED_ISR_RST) {
+               goto out;
+       }
+
+       NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+
+       for (i = 0; i < 100; i++) {
+               if ((NIC_INB(ED_P0_ISR) & ED_ISR_RST) ==
+                   ED_ISR_RST) {
+                       /* Ack the reset bit. */
+                       NIC_OUTB(ED_P0_ISR, ED_ISR_RST);
+                       break;
+               }
+               DELAY(100);
+       }
+
+       printf("ne: found\n");
+
+       /*
+        * This prevents packets from being stored in the NIC memory when
+        * the readmem routine turns on the start bit in the CR.
+        */
+       NIC_OUTB(ED_P0_RCR, ED_RCR_MON);
+
+       /* Temporarily initialize DCR for byte operations. */
+       NIC_OUTB(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+
+       NIC_OUTB(ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT);
+       NIC_OUTB(ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT);
+
+#ifdef HWADDR
+       for (i = 0; i < 6; i++)
+               myadr[i] = eth_myaddr[i] = HWADDR[i];
+#else
+{
+       uint8_t romdata[16];
+
+       ne2000_readmem(0, romdata, 16);
+       for (i = 0; i < 6; i++)
+               myadr[i] = eth_myaddr[i] = romdata[i*2];
+}
+#endif
+
+       if (dp8390_config())
+               goto out;
+
+#ifdef _STANDALONE
+       strncpy(bi_netif.ifname, "ne", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_ISA;
+       bi_netif.addr.iobase = NE_BASEREG;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+       return 1;
+out:
+       return 0;
+}
+
+void
+EtherStop(void) {
+       uint8_t tmp;
+
+       dp8390_stop();
+
+       tmp = ASIC_INB(NE2000_ASIC_RESET);
+       DELAY(10000);
+       ASIC_OUTB(NE2000_ASIC_RESET, tmp);
+       DELAY(5000);
+
+       NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+       DELAY(5000);
+}
+
+void
+ne2000_writemem(uint8_t *src, int dst, size_t len)
+{
+       size_t i;
+       int maxwait = 100;      /* about 120us */
+
+       /* Select page 0 registers. */
+       NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+
+       /* Reset remote DMA complete flag. */
+       NIC_OUTB(ED_P0_ISR, ED_ISR_RDC);
+
+       /* Set up DMA byte count. */
+       NIC_OUTB(ED_P0_RBCR0, len);
+       NIC_OUTB(ED_P0_RBCR1, len >> 8);
+
+       /* Set up destination address in NIC mem. */
+       NIC_OUTB(ED_P0_RSAR0, dst);
+       NIC_OUTB(ED_P0_RSAR1, dst >> 8);
+
+       /* Set remote DMA write. */
+       NIC_OUTB(ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+
+#ifdef NE_16BIT
+       for (i = 0; i < len; i += 2, src += 2)
+               ASIC_OUTW(NE2000_ASIC_DATA, *(uint16_t *)src);
+#else
+       for (i = 0; i < len; i++)
+               ASIC_OUTB(NE2000_ASIC_DATA, *src++);
+#endif
+
+       /*
+        * Wait for remote DMA to complete.  This is necessary because on the
+        * transmit side, data is handled internally by the NIC in bursts, and
+        * we can't start another remote DMA until this one completes.  Not
+        * waiting causes really bad things to happen - like the NIC wedging
+        * the bus.
+        */
+       while (((NIC_INB(ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait)
+               DELAY(1);
+
+       if (maxwait == 0)
+               printf("ne2000_writemem: failed to complete\n");
+}
+
+void
+ne2000_readmem(int src, uint8_t *dst, size_t amount)
+{
+       size_t i;
+
+       /* Select page 0 registers. */
+       NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+
+       /* Round up to a word. */
+       if (amount & 1)
+               ++amount;
+
+       /* Set up DMA byte count. */
+       NIC_OUTB(ED_P0_RBCR0, amount);
+       NIC_OUTB(ED_P0_RBCR1, amount >> 8);
+
+       /* Set up source address in NIC mem. */
+       NIC_OUTB(ED_P0_RSAR0, src);
+       NIC_OUTB(ED_P0_RSAR1, src >> 8);
+
+       NIC_OUTB(ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
+
+#ifdef NE_16BIT
+       for (i = 0; i < amount; i += 2, dst += 2)
+               *(uint16_t *)dst = ASIC_INW(NE2000_ASIC_DATA);
+#else
+       for (i = 0; i < amount; i++)
+               *dst++ = ASIC_INB(NE2000_ASIC_DATA);
+#endif
+}
diff --git a/sys/arch/i386/stand/lib/netif/ne.h b/sys/arch/i386/stand/lib/netif/ne.h
new file mode 100644 (file)
index 0000000..755a155
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: ne.h,v 1.3 2008/12/14 18:46:33 christos Exp $  */
+
+void ne2000_readmem(int, uint8_t *, size_t);
+void ne2000_writemem(uint8_t *, int, size_t);
diff --git a/sys/arch/i386/stand/lib/netif/netif_small.c b/sys/arch/i386/stand/lib/netif/netif_small.c
new file mode 100644 (file)
index 0000000..0a46233
--- /dev/null
@@ -0,0 +1,165 @@
+/*     $NetBSD: netif_small.c,v 1.12 2009/10/21 23:12:09 snj Exp $     */
+
+/* minimal netif - for boot ROMs we don't have to select between
+  several interfaces, and we have to save space
+
+  hacked from netbsd:sys/arch/mvme68k/stand/libsa/netif.c
+ */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libsa/net.h>
+
+#include "netif_small.h"
+#include "etherdrv.h"
+
+#ifdef NETIF_DEBUG
+int netif_debug = 1;
+#endif
+
+/* we allow for one socket only */
+static struct iodesc iosocket;
+
+struct iodesc *
+socktodesc(int sock)
+{
+       if (sock != 0) {
+               return NULL;
+       }
+       return &iosocket;
+}
+
+int
+netif_open(void)
+{
+       struct iodesc *io;
+
+       io = &iosocket;
+       if (io->io_netif) {
+#ifdef NETIF_DEBUG
+               printf("netif_open: device busy\n");
+#endif
+               return -1;
+       }
+       memset(io, 0, sizeof(*io));
+
+       if (!EtherInit(io->myea)) {
+               printf("EtherInit failed\n");
+               return -1;
+       }
+
+       io->io_netif = (void*)1; /* mark busy */
+
+       return 0;
+}
+
+void
+netif_close(int fd)
+{
+       struct iodesc *io;
+
+       if (fd != 0) {
+               return;
+       }
+
+       io = &iosocket;
+       if (io->io_netif) {
+               EtherStop();
+               io->io_netif = NULL;
+       }
+}
+
+/*
+ * Send a packet.  The ether header is already there.
+ * Return the length sent (or -1 on error).
+ */
+int
+netif_put(struct iodesc *desc, void *pkt, size_t len)
+{
+#ifdef NETIF_DEBUG
+       if (netif_debug) {
+               struct ether_header *eh;
+
+               printf("netif_put: desc=%p pkt=%p len=%d\n",
+                          desc, pkt, len);
+               eh = pkt;
+               printf("dst: %s ", ether_sprintf(eh->ether_dhost));
+               printf("src: %s ", ether_sprintf(eh->ether_shost));
+               printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
+       }
+#endif
+       return EtherSend(pkt, len);
+}
+
+/*
+ * Receive a packet, including the ether header.
+ * Return the total length received (or -1 on error).
+ */
+int
+netif_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timo)
+{
+       int len;
+       satime_t t;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("netif_get: pkt=%p, maxlen=%d, tmo=%d\n",
+                          pkt, maxlen, timo);
+#endif
+
+       t = getsecs();
+       len = 0;
+       while (((getsecs() - t) < timo) && !len) {
+               len = EtherReceive(pkt, maxlen);
+       }
+
+#ifdef NETIF_DEBUG
+       if (netif_debug) {
+               struct ether_header *eh = pkt;
+
+               printf("dst: %s ", ether_sprintf(eh->ether_dhost));
+               printf("src: %s ", ether_sprintf(eh->ether_shost));
+               printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
+       }
+#endif
+
+       return len;
+}
diff --git a/sys/arch/i386/stand/lib/netif/netif_small.h b/sys/arch/i386/stand/lib/netif/netif_small.h
new file mode 100644 (file)
index 0000000..2c80d02
--- /dev/null
@@ -0,0 +1,35 @@
+/*     $NetBSD: netif_small.h,v 1.5 2009/10/21 23:12:09 snj Exp $      */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <lib/libsa/iodesc.h>
+
+/* minimal netif - for boot ROMs we don't have to select between
+ several interfaces, and we have to save space */
+
+int netif_open(void);
+void netif_close(int);
diff --git a/sys/arch/i386/stand/lib/netif/pcnet_isapnp.c b/sys/arch/i386/stand/lib/netif/pcnet_isapnp.c
new file mode 100644 (file)
index 0000000..b45db94
--- /dev/null
@@ -0,0 +1,89 @@
+/*     $NetBSD: pcnet_isapnp.c,v 1.8 2008/12/14 18:46:33 christos Exp $        */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+
+#include <libi386.h>
+#include <isapnpvar.h>
+#include <isadmavar.h>
+#include <bootinfo.h>
+
+#include "etherdrv.h"
+#include "lance.h"
+
+#ifndef ISAPNPID
+#define ISAPNPID 0x516e0010 /* TKN0010 */
+#endif
+
+int lance_rap, lance_rdp;
+
+u_char eth_myaddr[6];
+
+extern void am7990_init(void);
+extern void am7990_stop(void);
+
+static struct btinfo_netif bi_netif;
+
+int
+EtherInit(unsigned char *myadr)
+{
+       int iobase, dmachan, i;
+
+       if (isapnp_finddev(ISAPNPID, &iobase, &dmachan)) {
+               printf("cannot find PCNET\n");
+               return 0;
+       }
+
+       printf("printf using PCNET @ %x\n", iobase);
+
+       lance_rap = iobase + 0x12;
+       lance_rdp = iobase + 0x10;
+
+       /* make sure it's stopped */
+       am7990_stop();
+
+       for (i = 0; i < 6; i++)
+               myadr[i] = eth_myaddr[i] = inb(iobase + i);
+
+       isa_dmacascade(dmachan);
+
+       am7990_init();
+
+       strncpy(bi_netif.ifname, "le", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_ISA;
+       bi_netif.addr.iobase = iobase;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+
+       return 1;
+}
diff --git a/sys/arch/i386/stand/lib/netif/pcnet_pci.c b/sys/arch/i386/stand/lib/netif/pcnet_pci.c
new file mode 100644 (file)
index 0000000..a0712ac
--- /dev/null
@@ -0,0 +1,99 @@
+/*     $NetBSD: pcnet_pci.c,v 1.8 2008/12/14 18:46:33 christos Exp $   */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <machine/pio.h>
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+
+#include <libi386.h>
+#include <pcivar.h>
+#include <bootinfo.h>
+
+#include "etherdrv.h"
+#include "lance.h"
+
+int lance_rap, lance_rdp;
+
+static pcihdl_t hdl;
+
+u_char eth_myaddr[6];
+
+extern void am7990_init(void);
+extern void am7990_stop(void);
+
+static struct btinfo_netif bi_netif;
+
+int
+EtherInit(unsigned char *myadr)
+{
+  int iobase, pcicsr, i;
+
+  if (pcicheck() == -1) {
+    printf("cannot access PCI\n");
+    return 0;
+  }
+
+  if (pcifinddev(0x1022, 0x2000, &hdl)) {
+    printf("cannot find PCNET\n");
+    return 0;
+  }
+
+  if (pcicfgread(&hdl, 0x10, &iobase) || !(iobase & 1)) {
+    printf("cannot map IO space\n");
+    return 0;
+  }
+  iobase &= 0xfffffffc;
+
+  lance_rap = iobase + 0x12;
+  lance_rdp = iobase + 0x10;
+
+  /* make sure it's stopped */
+  am7990_stop();
+
+  /* enable bus mastering in PCI command register */
+  if (pcicfgread(&hdl, 0x04, &pcicsr)
+     || pcicfgwrite(&hdl, 0x04, pcicsr | 4)) {
+    printf("cannot enable DMA\n");
+    return 0;
+  }
+
+  for (i = 0; i < 6; i++)
+         myadr[i] = eth_myaddr[i] = inb(iobase + i);
+
+  am7990_init();
+
+  strncpy(bi_netif.ifname, "le", sizeof(bi_netif.ifname));
+  bi_netif.bus = BI_BUS_PCI;
+  bi_netif.addr.tag = hdl;
+
+  BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+
+  return 1;
+}
diff --git a/sys/arch/i386/stand/lib/netif/wd80x3.c b/sys/arch/i386/stand/lib/netif/wd80x3.c
new file mode 100644 (file)
index 0000000..e913f8d
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: wd80x3.c,v 1.10 2008/12/14 18:46:33 christos Exp $     */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
+ * adapters.
+ *
+ * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * Copyright (C) 1993, David Greenman.  This software may be used, modified,
+ * copied, distributed, and sold, in both source and binary form provided that
+ * the above copyright and these terms are retained.  Under no circumstances is
+ * the author responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its use.
+ */
+
+/*
+ * Device driver for the Western Digital/SMC 8003 and 8013 series,
+ * and the SMC Elite Ultra (8216).
+ */
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <lib/libsa/stand.h>
+#include <libi386.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#include <bootinfo.h>
+#endif
+
+#include "etherdrv.h"
+#include <dev/ic/dp8390reg.h>
+#include "dp8390.h"
+#include <dev/ic/wereg.h>
+
+#ifndef BASEREG
+#define BASEREG 0x240
+#define BASEMEM 0xd0000
+#endif
+
+#define        WD_BASEREG BASEREG
+#define        WD_BASEMEM BASEMEM
+
+#ifndef _STANDALONE
+extern int mapio(void);
+#endif
+
+u_char eth_myaddr[6];
+
+static uint8_t we_type;
+static int we_is16bit;
+
+#ifdef _STANDALONE
+static struct btinfo_netif bi_netif;
+#endif
+
+const char *
+we_params(void)
+{
+       const char *typestr;
+
+       dp8390_memsize = 8192;
+
+       we_type = inb(WD_BASEREG + WE_CARD_ID);
+       switch (we_type) {
+#ifdef SUPPORT_WD80X3
+       case WE_TYPE_WD8003S:
+               typestr = "WD8003S";
+               break;
+       case WE_TYPE_WD8003E:
+               typestr = "WD8003E";
+               break;
+       case WE_TYPE_WD8003EB:
+               typestr = "WD8003EB";
+               break;
+       case WE_TYPE_WD8003W:
+               typestr = "WD8003W";
+               break;
+       case WE_TYPE_WD8013EBT:
+               typestr = "WD8013EBT";
+               dp8390_memsize = 16384;
+               we_is16bit = 1;
+               break;
+       case WE_TYPE_WD8013W:
+               typestr = "WD8013W";
+               dp8390_memsize = 16384;
+               we_is16bit = 1;
+               break;
+       case WE_TYPE_WD8013EP:          /* also WD8003EP */
+               if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) {
+                       we_is16bit = 1;
+                       dp8390_memsize = 16384;
+                       typestr = "WD8013EP";
+               } else
+                       typestr = "WD8003EP";
+               break;
+       case WE_TYPE_WD8013WC:
+               typestr = "WD8013WC";
+               dp8390_memsize = 16384;
+               we_is16bit = 1;
+               break;
+       case WE_TYPE_WD8013EBP:
+               typestr = "WD8013EBP";
+               dp8390_memsize = 16384;
+               we_is16bit = 1;
+               break;
+       case WE_TYPE_WD8013EPC:
+               typestr = "WD8013EPC";
+               dp8390_memsize = 16384;
+               we_is16bit = 1;
+               break;
+#endif
+#ifdef SUPPORT_SMC_ULTRA
+       case WE_TYPE_SMC8216C:
+       case WE_TYPE_SMC8216T:
+           {
+               uint8_t hwr;
+
+               typestr = (we_type == WE_TYPE_SMC8216C) ?
+                   "SMC8216/SMC8216C" : "SMC8216T";
+
+               hwr = inb(WD_BASEREG + WE790_HWR);
+               outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH);
+               switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) {
+               case WE790_RAR_SZ64:
+                       dp8390_memsize = 65536;
+                       break;
+               case WE790_RAR_SZ32:
+                       dp8390_memsize = 32768;
+                       break;
+               case WE790_RAR_SZ16:
+                       dp8390_memsize = 16384;
+                       break;
+               case WE790_RAR_SZ8:
+                       /* 8216 has 16K shared mem -- 8416 has 8K */
+                       typestr = (we_type == WE_TYPE_SMC8216C) ?
+                           "SMC8416C/SMC8416BT" : "SMC8416T";
+                       dp8390_memsize = 8192;
+                       break;
+               }
+               outb(WD_BASEREG + WE790_HWR, hwr);
+
+               we_is16bit = 1;
+#ifdef SUPPORT_WD80X3
+               dp8390_is790 = 1;
+#endif
+               break;
+           }
+#endif
+       default:
+               /* Not one we recognize. */
+               return NULL;
+       }
+
+       /*
+        * Make some adjustments to initial values depending on what is
+        * found in the ICR.
+        */
+       if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) &&
+           (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) {
+               we_is16bit = 0;
+               dp8390_memsize = 8192;
+       }
+
+#ifdef WE_DEBUG
+       {
+               int i;
+
+               printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, "
+                   "memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize);
+               for (i = 0; i < 8; i++)
+                       printf("     %d -> 0x%x\n", i,
+                           inb(WD_BASEREG + i));
+       }
+#endif
+
+       return typestr;
+}
+
+int
+EtherInit(unsigned char *myadr)
+{
+       const char *typestr;
+       uint8_t x;
+       int i;
+       uint8_t laar_proto;
+       uint8_t msr_proto;
+
+       dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET;
+       dp8390_membase = WD_BASEMEM;
+
+#ifndef _STANDALONE
+       if (mapio()) {
+               printf("no IO access\n");
+               return 0;
+       }
+#endif
+
+       for (x = 0, i = 0; i < 8; i++)
+               x += inb(WD_BASEREG + WE_PROM + i);
+
+       if (x != WE_ROM_CHECKSUM_TOTAL)
+               return 0;
+
+       /* reset the ethernet card */
+       outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
+       delay(100);
+       outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST);
+       delay(5000);
+
+       typestr = we_params();
+       if (!typestr)
+               return 0;
+
+       printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n",
+              typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize);
+
+       /* get ethernet address */
+       for (i = 0; i < 6; i++)
+               eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i);
+
+       /*
+        * Set upper address bits and 8/16 bit access to shared memory.
+        */
+       if (dp8390_is790) {
+               laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN;
+               outb(WD_BASEREG + WE_LAAR, laar_proto |
+                    (we_is16bit ? WE_LAAR_M16EN : 0));
+       } else if ((we_type & WE_SOFTCONFIG) ||
+                  (we_type == WE_TYPE_WD8013EBT)) {
+               laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI;
+               if (we_is16bit)
+                       laar_proto |= WE_LAAR_L16EN;
+               outb(WD_BASEREG + WE_LAAR, laar_proto |
+                    (we_is16bit ? WE_LAAR_M16EN : 0));
+       }
+
+       /*
+        * Set address and enable interface shared memory.
+        */
+       if (dp8390_is790) {
+               /* XXX MAGIC CONSTANTS XXX */
+               x = inb(WD_BASEREG + 0x04);
+               outb(WD_BASEREG + 0x04, x | 0x80);
+               outb(WD_BASEREG + 0x0b,
+                   ((WD_BASEMEM >> 13) & 0x0f) |
+                   ((WD_BASEMEM >> 11) & 0x40) |
+                   (inb(WD_BASEREG + 0x0b) & 0xb0));
+               outb(WD_BASEREG + 0x04, x);
+               msr_proto = 0x00;
+               dp8390_cr_proto = 0x00;
+       } else {
+               msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR;
+               dp8390_cr_proto = ED_CR_RD2;
+       }
+
+       outb(WD_BASEREG +  WE_MSR, msr_proto | WE_MSR_MENB);
+       delay(2);
+
+       /*
+        * DCR gets:
+        *
+        *      FIFO threshold to 8, No auto-init Remote DMA,
+        *      byte order=80x86.
+        *
+        * 16-bit cards also get word-wide DMA transfers.
+        */
+       dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0);
+
+       if (dp8390_config())
+               return 0;
+
+#ifdef _STANDALONE
+       strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname));
+       bi_netif.bus = BI_BUS_ISA;
+       bi_netif.addr.iobase = WD_BASEREG;
+
+       BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
+#endif
+       return 1;
+}
+
+/*
+ * Stop ethernet board
+ */
+void
+EtherStop(void) {
+       /* stop dp8390, followed by a board reset */
+       dp8390_stop();
+       outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
+       outb(WD_BASEREG + WE_MSR, 0);
+}
diff --git a/sys/arch/i386/stand/lib/parseutils.c b/sys/arch/i386/stand/lib/parseutils.c
new file mode 100644 (file)
index 0000000..37099d1
--- /dev/null
@@ -0,0 +1,151 @@
+/*     $NetBSD: parseutils.c,v 1.6 2011/08/18 13:20:04 christos Exp $  */
+
+/*
+ * Copyright (c) 1996, 1997
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1996, 1997
+ *     Perry E. Metzger.  All rights reserved.
+ * Copyright (c) 1997
+ *     Jason R. Thorpe.  All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgements:
+ *     This product includes software developed for the NetBSD Project
+ *     by Matthias Drochner.
+ *     This product includes software developed for the NetBSD Project
+ *     by Perry E. Metzger.
+ * 4. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <lib/libkern/libkern.h>
+#include <lib/libsa/stand.h>
+#include <sys/boot_flag.h>
+
+#include "libi386.h"
+
+/*
+ * chops the head from the arguments and returns the arguments if any,
+ * or possibly an empty string.
+ */
+char *
+gettrailer(char *arg)
+{
+       char *options;
+
+       for (options = arg; *options; options++) {
+               switch (*options) {
+               case ' ':
+               case '\t':
+                       *options++ = '\0';
+                       break;
+               default:
+                       continue;
+               }
+               break;
+       }
+       if (*options == '\0')
+               return "";
+
+       /* trim leading blanks/tabs */
+       while (*options == ' ' || *options == '\t')
+               options++;
+
+       return options;
+}
+
+int
+parseopts(const char *opts, int *howto)
+{
+       int r, tmpopt = 0;
+
+       opts++;         /* skip - */
+       while (*opts) {
+               r = 0;
+               BOOT_FLAG(*opts, r);
+               if (r == 0) {
+                       printf("-%c: unknown flag\n", *opts);
+                       command_help(NULL);
+                       return 0;
+               }
+               tmpopt |= r;
+               opts++;
+               if (*opts == ' ' || *opts == '\t') {
+                       do
+                               opts++;         /* skip whitespace */
+                       while (*opts == ' ' || *opts == '\t');
+                       if (*opts == '-')
+                               opts++;         /* skip - */
+                       else if (*opts != '\0') {
+                               printf("invalid arguments\n");
+                               command_help(NULL);
+                               return 0;
+                       }
+               }
+       }
+
+       *howto = tmpopt;
+       return 1;
+}
+
+int
+parseboot(char *arg, char **filename, int *howto)
+{
+       char *opts = NULL;
+
+       *filename = 0;
+       *howto = 0;
+
+       /* if there were no arguments */
+       if (!*arg)
+               return 1;
+
+       /* format is... */
+       /* [[xxNx:]filename] [-adqsv] */
+
+       /* check for just args */
+       if (arg[0] == '-')
+               opts = arg;
+       else {
+               /* there's a file name */
+               *filename = arg;
+
+               opts = gettrailer(arg);
+               if (!*opts)
+                       opts = NULL;
+               else if (*opts != '-') {
+                       printf("invalid arguments\n");
+                       command_help(NULL);
+                       return 0;
+               }
+       }
+
+       /* at this point, we have dealt with filenames. */
+
+       /* now, deal with options */
+       if (opts) {
+               if (parseopts(opts, howto) == 0)
+                       return 0;
+       }
+
+       return 1;
+}
diff --git a/sys/arch/i386/stand/lib/pcio.c b/sys/arch/i386/stand/lib/pcio.c
new file mode 100644 (file)
index 0000000..d03e446
--- /dev/null
@@ -0,0 +1,378 @@
+/*     $NetBSD: pcio.c,v 1.30 2011/06/08 16:04:40 joerg Exp $   */
+
+/*
+ * Copyright (c) 1996, 1997
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * console I/O
+ * needs lowlevel routines from conio.S and comio.S
+ */
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#include <sys/bootblock.h>
+
+#include "libi386.h"
+#include "bootinfo.h"
+
+extern struct x86_boot_params boot_params;
+
+struct btinfo_console btinfo_console;
+
+#ifdef SUPPORT_SERIAL
+static int iodev;
+
+#ifdef DIRECT_SERIAL
+#include "comio_direct.h"
+
+#define cominit_x()    btinfo_console.speed = \
+                           cominit_d(btinfo_console.addr, btinfo_console.speed)
+#define computc_x(ch)  computc_d(ch, btinfo_console.addr)
+#define comgetc_x()    comgetc_d(btinfo_console.addr)
+#define comstatus_x()  comstatus_d(btinfo_console.addr)
+
+#else
+#define cominit_x()    cominit(iodev - CONSDEV_COM0)
+#define computc_x(ch)  computc(ch, iodev - CONSDEV_COM0)
+#define comgetc_x()    comgetc(iodev - CONSDEV_COM0)
+#define comstatus_x()  comstatus(iodev - CONSDEV_COM0)
+
+#endif /* DIRECT_SERIAL */
+
+static int getcomaddr(int);
+#endif /* SUPPORT_SERIAL */
+
+#define POLL_FREQ 10
+
+static void
+wait(int us)
+{
+       int prev = biosgetsystime();
+       int tgt = prev + (20 * us) / 1000000;
+       int new;
+
+       while ((new = biosgetsystime()) < tgt) {
+               if (new < prev) /* XXX timer wrapped */
+                       break;
+               prev = new;
+       }
+}
+
+#ifdef SUPPORT_SERIAL
+static int
+getcomaddr(int idx)
+{
+       short addr;
+#ifdef CONSADDR
+       if (CONSADDR != 0)
+               return CONSADDR;
+#endif
+       /* read in BIOS data area */
+       pvbcopy((void *)(0x400 + 2 * idx), &addr, 2);
+       return addr;
+}
+#endif
+
+void
+clear_pc_screen(void)
+{
+#ifdef SUPPORT_SERIAL
+       /* Clear the screen if we are on a glass tty. */
+       if (iodev == CONSDEV_PC)
+               conclr();
+#endif
+}
+
+void
+initio(int dev)
+{
+#ifdef SUPPORT_SERIAL
+       int i;
+
+#if defined(DIRECT_SERIAL) && defined(CONSPEED)
+       btinfo_console.speed = CONSPEED;
+#else
+       btinfo_console.speed = 9600;
+#endif
+
+       switch (dev) {
+       case CONSDEV_AUTO:
+               for (i = 0; i < 3; i++) {
+                       iodev = CONSDEV_COM0 + i;
+                       btinfo_console.addr = getcomaddr(i);
+                       if (!btinfo_console.addr)
+                               break;
+                       conputc('0' + i); /* to tell user what happens */
+                       cominit_x();
+#ifdef DIRECT_SERIAL
+                       /* check for:
+                        *  1. successful output
+                        *  2. optionally, keypress within 7s
+                        */
+                       if (    computc_x(':') &&
+                               computc_x('-') &&
+                               computc_x('(')
+#ifdef COMCONS_KEYPRESS
+                          && awaitkey(7, 0)
+#endif
+                          )
+                               goto ok;
+#else /* ! DIRECT_SERIAL */
+                       /*
+                        * serial console must have hardware handshake!
+                        * check:
+                        *  1. character output without error
+                        *  2. status bits for modem ready set
+                        *     (status seems only useful after character output)
+                        *  3. optionally, keypress within 7s
+                        */
+                       if (!(computc_x('@') & 0x80)
+                           && (comstatus_x() & 0x00b0)
+#ifdef COMCONS_KEYPRESS
+                           && awaitkey(7, 0)
+#endif
+                           )
+                               goto ok;
+#endif /* DIRECT_SERIAL */
+               }
+               iodev = CONSDEV_PC;
+ok:
+               break;
+       case CONSDEV_COM0:
+       case CONSDEV_COM1:
+       case CONSDEV_COM2:
+       case CONSDEV_COM3:
+               iodev = dev;
+               btinfo_console.addr = getcomaddr(iodev - CONSDEV_COM0);
+               if (!btinfo_console.addr)
+                       goto nocom;
+               cominit_x();
+               break;
+       case CONSDEV_COM0KBD:
+       case CONSDEV_COM1KBD:
+       case CONSDEV_COM2KBD:
+       case CONSDEV_COM3KBD:
+               iodev = dev - CONSDEV_COM0KBD + CONSDEV_COM0;
+               i = iodev - CONSDEV_COM0;
+               btinfo_console.addr = getcomaddr(i);
+               if (!btinfo_console.addr)
+                       goto nocom;
+               conputc('0' + i); /* to tell user what happens */
+               cominit_x();
+#ifdef DIRECT_SERIAL
+                       /* check for:
+                        *  1. successful output
+                        *  2. optionally, keypress within 7s
+                        */
+                       if (    computc_x(':') &&
+                               computc_x('-') &&
+                               computc_x('(')
+#ifdef COMCONS_KEYPRESS
+                          && awaitkey(7, 0)
+#endif
+                          )
+                               break;
+#else /* ! DIRECT_SERIAL */
+                       /*
+                        * serial console must have hardware handshake!
+                        * check:
+                        *  1. character output without error
+                        *  2. status bits for modem ready set
+                        *     (status seems only useful after character output)
+                        *  3. optionally, keypress within 7s
+                        */
+                       if (!(computc_x('@') & 0x80)
+                           && (comstatus_x() & 0x00b0)
+#ifdef COMCONS_KEYPRESS
+                           && awaitkey(7, 0)
+#endif
+                           )
+                               break;
+#endif /* DIRECT_SERIAL */
+       default:
+nocom:
+               iodev = CONSDEV_PC;
+               break;
+       }
+       conputc('\015');
+       conputc('\n');
+       strncpy(btinfo_console.devname, iodev == CONSDEV_PC ? "pc" : "com", 16);
+
+#else /* !SUPPORT_SERIAL */
+       btinfo_console.devname[0] = 'p';
+       btinfo_console.devname[1] = 'c';
+       btinfo_console.devname[2] = 0;
+#endif /* SUPPORT_SERIAL */
+}
+
+static inline void internal_putchar(int);
+
+static inline void
+internal_putchar(int c)
+{
+#ifdef SUPPORT_SERIAL
+       switch (iodev) {
+       case CONSDEV_PC:
+#endif
+               conputc(c);
+#ifdef SUPPORT_SERIAL
+               break;
+       case CONSDEV_COM0:
+       case CONSDEV_COM1:
+       case CONSDEV_COM2:
+       case CONSDEV_COM3:
+               computc_x(c);
+               break;
+       }
+#endif
+}
+
+void
+putchar(int c)
+{
+       if (c == '\n')
+               internal_putchar('\r');
+       internal_putchar(c);
+}
+
+int
+getchar(void)
+{
+       int c;
+#ifdef SUPPORT_SERIAL
+       switch (iodev) {
+       default: /* to make gcc -Wall happy... */
+       case CONSDEV_PC:
+#endif
+               while (!coniskey())
+                       ;
+               c = congetc();
+#ifdef CONSOLE_KEYMAP
+               {
+                       char *cp = strchr(CONSOLE_KEYMAP, c);
+                       if (cp != 0 && cp[1] != 0)
+                               c = cp[1];
+               }
+#endif
+               return c;
+#ifdef SUPPORT_SERIAL
+       case CONSDEV_COM0:
+       case CONSDEV_COM1:
+       case CONSDEV_COM2:
+       case CONSDEV_COM3:
+#ifdef DIRECT_SERIAL
+               c = comgetc_x();
+#else
+               do {
+                       c = comgetc_x();
+               } while ((c >> 8) == 0xe0); /* catch timeout */
+#ifdef COMDEBUG
+               if (c & 0x8000) {
+                       printf("com input %x, status %x\n",
+                              c, comstatus_x());
+               }
+#endif
+               c &= 0xff;
+#endif /* DIRECT_SERIAL */
+               return c;
+       }
+#endif /* SUPPORT_SERIAL */
+}
+
+int
+iskey(int intr)
+{
+#ifdef SUPPORT_SERIAL
+       switch (iodev) {
+       default: /* to make gcc -Wall happy... */
+       case CONSDEV_PC:
+#endif
+               return (intr && conisshift()) || coniskey();
+#ifdef SUPPORT_SERIAL
+       case CONSDEV_COM0:
+       case CONSDEV_COM1:
+       case CONSDEV_COM2:
+       case CONSDEV_COM3:
+#ifdef DIRECT_SERIAL
+               return !!comstatus_x();
+#else
+               return !!(comstatus_x() & 0x0100);
+#endif
+       }
+#endif /* SUPPORT_SERIAL */
+}
+
+char
+awaitkey(int timeout, int tell)
+{
+       int i;
+       char c = 0;
+
+       i = timeout * POLL_FREQ;
+
+       for (;;) {
+               if (tell && (i % POLL_FREQ) == 0) {
+                       char numbuf[32];
+                       int len;
+
+                       len = snprintf(numbuf, sizeof(numbuf), "%d seconds. ",
+                           i/POLL_FREQ);
+                       if (len > 0 && len < sizeof(numbuf)) {
+                               char *p = numbuf;
+
+                               printf("%s", numbuf);
+                               while (*p)
+                                       *p++ = '\b';
+                               printf("%s", numbuf);
+                       }
+               }
+               if (iskey(1)) {
+                       /* flush input buffer */
+                       while (iskey(0))
+                               c = getchar();
+                       if (c == 0)
+                               c = -1;
+                       goto out;
+               }
+               if (i--)
+                       wait(1000000 / POLL_FREQ);
+               else
+                       break;
+       }
+
+out:
+       if (tell)
+               printf("0 seconds.     \n");
+
+       return c;
+}
+
+void
+wait_sec(int sec)
+{
+
+       wait(sec * 1000000);
+}
diff --git a/sys/arch/i386/stand/lib/pcivar.h b/sys/arch/i386/stand/lib/pcivar.h
new file mode 100644 (file)
index 0000000..f6f9e43
--- /dev/null
@@ -0,0 +1,35 @@
+/*     $NetBSD: pcivar.h,v 1.4 2008/12/14 17:03:43 christos Exp $      */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+typedef unsigned int pcihdl_t;
+
+int pcicheck(void);
+int pcifinddev(int, int, pcihdl_t*);
+int pcicfgread(pcihdl_t*, int, int*);
+int pcicfgwrite(pcihdl_t*, int, int);
diff --git a/sys/arch/i386/stand/lib/pread.c b/sys/arch/i386/stand/lib/pread.c
new file mode 100644 (file)
index 0000000..fc273a7
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: pread.c,v 1.7 2008/12/14 17:03:43 christos Exp $        */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* read into destination in flat addr space */
+
+#include <lib/libsa/stand.h>
+
+#include "libi386.h"
+
+#ifdef SAVE_MEMORY
+#define BUFSIZE (1*1024)
+#else
+#define BUFSIZE (4*1024)
+#endif
+
+static char     *buf;
+
+ssize_t
+pread(int fd, void *dest, size_t size)
+{
+       int             rsize;
+
+       if (!buf)
+               buf = alloc(BUFSIZE);
+
+       rsize = size;
+       while (rsize > 0) {
+               int             count, got;
+
+               count = (rsize < BUFSIZE ? rsize : BUFSIZE);
+
+               got = read(fd, buf, count);
+               if (got < 0)
+                       return -1;
+
+               /* put to physical space */
+               vpbcopy(buf, dest, got);
+
+               dest += got;
+               rsize -= got;
+               if (got < count)
+                       break;  /* EOF */
+       }
+       return size - rsize;
+}
diff --git a/sys/arch/i386/stand/lib/printmemlist.c b/sys/arch/i386/stand/lib/printmemlist.c
new file mode 100644 (file)
index 0000000..bbf5153
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: printmemlist.c,v 1.2 2008/12/14 17:03:43 christos Exp $        */
+/*
+ * Copyright (c) 1999
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <lib/libsa/stand.h>
+#include "libi386.h"
+
+extern int getmementry(int *, int *);
+
+static char *memtypes[] = {
+       "available",
+       "reserved",
+       "ACPI reclaimable",
+       "ACPI NVS"
+};
+
+void
+printmemlist(void)
+{
+        int buf[5], i;
+       char *type;
+
+        i = 0;
+        do {
+                if (getmementry(&i, buf))
+                        break;
+               if (buf[4] < 1 || buf[4] > 4)
+                       type = "invalid entry";
+               else
+                       type = memtypes[buf[4] - 1];
+               printf("%x:%x/%x:%x: %s\n", buf[1], buf[0], buf[3], buf[2],
+                      type);
+        } while (i);
+}
diff --git a/sys/arch/i386/stand/lib/putstr.S b/sys/arch/i386/stand/lib/putstr.S
new file mode 100644 (file)
index 0000000..d29ae9a
--- /dev/null
@@ -0,0 +1,84 @@
+/*     $NetBSD: putstr.S,v 1.2 2008/04/28 20:23:25 martin Exp $        */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Diagnostic print routines callable from 32bit C code during early
+ * parts of the boot process.
+ */
+
+/*
+ * void putstr(const char *)
+ *
+ * display message on console
+ * bugs: message address must be less than 64k
+ */
+
+       .globl  _C_LABEL(putstr)
+_C_LABEL(putstr):
+       .code32
+       movl    4(%esp), %eax
+       pusha
+       movl    %eax, %esi
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       movl    %esi, %eax
+       call    message
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+       popa
+       ret
+
+/*
+ * void putint(int)
+ *
+ * display value on console as 8 hex digits followed by a space
+ */
+
+       .globl  _C_LABEL(putint)
+_C_LABEL(putint):
+       .code32
+       movl    4(%esp), %eax
+       pusha
+
+       call    _C_LABEL(prot_to_real)
+       .code16
+
+       call    dump_eax
+
+       calll   _C_LABEL(real_to_prot)
+       .code32
+       popa
+       ret
diff --git a/sys/arch/i386/stand/lib/putstr32.S b/sys/arch/i386/stand/lib/putstr32.S
new file mode 100644 (file)
index 0000000..e700dd5
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: putstr32.S,v 1.1 2011/06/02 18:53:00 dsl Exp $ */
+
+/*-
+ * Copyright (c) 20011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Diagnostic print routines callable from 32bit C code during early
+ * parts of the boot process.
+ */
+
+/*
+ * void putstr(const char *)
+ *
+ * display message on serial port
+ */
+
+       .globl  _C_LABEL(putstr32)
+_C_LABEL(putstr32):
+       .code32
+       push    %esi
+       movl    8(%esp), %esi
+
+       call    message32
+
+       pop     %esi
+       ret
+
+/*
+ * void putint(int)
+ *
+ * display value on serial port as 8 hex digits followed by a space
+ */
+
+       .globl  _C_LABEL(putint32)
+_C_LABEL(putint32):
+       .code32
+       movl    4(%esp), %eax
+
+       call    dump_eax32
+
+       ret
diff --git a/sys/arch/i386/stand/lib/pvcopy.S b/sys/arch/i386/stand/lib/pvcopy.S
new file mode 100644 (file)
index 0000000..d73bff5
--- /dev/null
@@ -0,0 +1,115 @@
+/*     $NetBSD: pvcopy.S,v 1.2 2008/04/28 20:23:25 martin Exp $        */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Routines to copy to/from absolute virtual addresses.
+ * Needed because the boot code runs with %ds having a 64k offset
+ * whereas Unix runs with a zero offset.
+ *
+ * These routines are optimised for code space, not execution speed.
+ */
+
+/*
+ * pbzero(void *dst, int cnt)
+ *     zero absolute virtual memory
+ */
+ENTRY(pbzero)
+       .code32
+       push    %edi
+       push    %es
+       mov     12(%esp),%edi
+       mov     16(%esp),%ecx
+
+       mov     $flatdataseg, %ax       /* selector with offset == 0 */
+       mov     %ax, %es
+       xor     %eax,%eax
+
+       cld
+       rep
+       stosb
+
+       pop     %es
+       pop     %edi
+       ret
+
+/*
+ * vpbcopy(const void *src, void *dst, int cnt)
+ *     Copy to absolute virtual address
+ */
+ENTRY(vpbcopy)
+       .code32
+       push    %esi
+       push    %edi
+       push    %es
+       mov     16(%esp),%esi
+       mov     20(%esp),%edi
+       mov     24(%esp),%ecx
+
+       mov     $flatdataseg, %ax       /* selector with offset == 0 */
+       mov     %ax, %es
+       xor     %eax,%eax
+
+       cld
+       rep
+       movsb
+
+       popl    %es
+       popl    %edi
+       popl    %esi
+       ret
+
+/*
+ * pvbcopy(const void *src, void *dst, int cnt)
+ *     Copy from absolute virtual address
+ */
+ENTRY(pvbcopy)
+       .code32
+       push    %esi
+       push    %edi
+       push    %ds
+       mov     16(%esp),%esi
+       mov     20(%esp),%edi
+       mov     24(%esp),%ecx
+
+       mov     $flatdataseg, %ax       /* selector with offset == 0 */
+       mov     %ax, %ds
+       xor     %eax,%eax
+
+       cld
+       rep
+       movsb
+
+       popl    %ds
+       popl    %edi
+       popl    %esi
+       ret
diff --git a/sys/arch/i386/stand/lib/rasops.c b/sys/arch/i386/stand/lib/rasops.c
new file mode 100644 (file)
index 0000000..70b353b
--- /dev/null
@@ -0,0 +1,91 @@
+/* $NetBSD: rasops.c,v 1.1 2009/02/16 22:39:30 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Andrew Doran.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <lib/libsa/stand.h>
+
+/* ANSI colormap (R,G,B). Upper 8 are high-intensity */
+const uint8_t rasops_cmap[256*3] = {
+       0x00, 0x00, 0x00, /* black */
+       0x7f, 0x00, 0x00, /* red */
+       0x00, 0x7f, 0x00, /* green */
+       0x7f, 0x7f, 0x00, /* brown */
+       0x00, 0x00, 0x7f, /* blue */
+       0x7f, 0x00, 0x7f, /* magenta */
+       0x00, 0x7f, 0x7f, /* cyan */
+       0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
+
+       0x7f, 0x7f, 0x7f, /* black */
+       0xff, 0x00, 0x00, /* red */
+       0x00, 0xff, 0x00, /* green */
+       0xff, 0xff, 0x00, /* brown */
+       0x00, 0x00, 0xff, /* blue */
+       0xff, 0x00, 0xff, /* magenta */
+       0x00, 0xff, 0xff, /* cyan */
+       0xff, 0xff, 0xff, /* white */
+
+       /*
+        * For the cursor, we need at least the last (255th)
+        * color to be white. Fill up white completely for
+        * simplicity.
+        */
+#define _CMWHITE 0xff, 0xff, 0xff,
+#define _CMWHITE16     _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
+                       _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
+                       _CMWHITE _CMWHITE _CMWHITE _CMWHITE \
+                       _CMWHITE _CMWHITE _CMWHITE _CMWHITE
+       _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
+       _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16
+       _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 /* but not the last one */
+#undef _CMWHITE16
+#undef _CMWHITE
+
+       /*
+        * For the cursor the fg/bg indices are bit inverted, so
+        * provide complimentary colors in the upper 16 entries.
+        */
+       0x7f, 0x7f, 0x7f, /* black */
+       0xff, 0x00, 0x00, /* red */
+       0x00, 0xff, 0x00, /* green */
+       0xff, 0xff, 0x00, /* brown */
+       0x00, 0x00, 0xff, /* blue */
+       0xff, 0x00, 0xff, /* magenta */
+       0x00, 0xff, 0xff, /* cyan */
+       0xff, 0xff, 0xff, /* white */
+
+       0x00, 0x00, 0x00, /* black */
+       0x7f, 0x00, 0x00, /* red */
+       0x00, 0x7f, 0x00, /* green */
+       0x7f, 0x7f, 0x00, /* brown */
+       0x00, 0x00, 0x7f, /* blue */
+       0x7f, 0x00, 0x7f, /* magenta */
+       0x00, 0x7f, 0x7f, /* cyan */
+       0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
+};
diff --git a/sys/arch/i386/stand/lib/realprot.S b/sys/arch/i386/stand/lib/realprot.S
new file mode 100644 (file)
index 0000000..2d4bf93
--- /dev/null
@@ -0,0 +1,296 @@
+/*     $NetBSD: realprot.S,v 1.10 2010/12/19 17:18:23 jakllsch Exp $   */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Loosely based on code from stand/lib/libcrt/bootsect/start_bootsect.S
+ */
+
+#include <machine/asm.h>
+
+#define        CR0_PE          1
+
+       .text
+       .align  16
+gdt:
+       .word   0, 0
+       .byte   0, 0x00, 0x00, 0
+
+       /* kernel code segment */
+       .globl flatcodeseg
+flatcodeseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9f, 0xcf, 0
+
+       /* kernel data segment */
+       .globl flatdataseg
+flatdataseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x93, 0xcf, 0
+
+       /* boot code segment, base will be patched */
+bootcodeseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9e, 0x4f, 0
+
+       /* boot data segment, base will be patched */
+bootdataseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x92, 0xcf, 0
+
+       /* 16 bit real mode, base will be patched */
+bootrealseg = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x9e, 0x00, 0
+
+       /* limits (etc) for data segment in real mode */
+bootrealdata = . - gdt
+       .word   0xffff, 0
+       .byte   0, 0x92, 0x00, 0
+gdtlen = . - gdt
+
+       .align  16
+gdtarg:
+       .word   gdtlen-1                /* limit */
+       .long   0                       /* physical addr, will be inserted */
+
+toreal:        .word   xreal                   /* off:seg address for indirect jump */
+ourseg:        .word   0                       /* real mode code and data segment */
+
+stkseg:        .word   0                       /* real mode stack segment */
+stkdif:        .long   0                       /* diff. between real and prot sp */
+
+       .global gdt_fixup
+gdt_fixup:
+       .code16
+       pushl   %eax
+       pushl   %edx
+
+       xorl    %eax, %eax
+       mov     %cs, %ax
+       mov     %ax, ourseg
+       /* sort out stuff for %ss != %ds */
+       xorl    %edx, %edx
+       movw    %ss, %dx
+       movw    %dx, stkseg
+       subl    %eax, %edx
+       shll    $4, %edx
+       movl    %edx, stkdif
+
+       /* fix up GDT entries for bootstrap */
+       mov     %ax, %dx
+       shll    $4, %eax
+       shr     $12, %dx
+
+#define FIXUP(gdt_index) \
+       movw    %ax, gdt+gdt_index+2; \
+       movb    %dl, gdt+gdt_index+4
+
+       FIXUP(bootcodeseg)
+       FIXUP(bootrealseg)
+       FIXUP(bootdataseg)
+
+       /* fix up GDT pointer */
+       addl    $gdt, %eax
+       movl    %eax, gdtarg+2
+
+       popl    %edx
+       popl    %eax
+       ret
+
+/*
+ * real_to_prot()
+ *
+ * Switch CPU to 32bit protected mode to execute C.
+ *
+ * NB: Call with the 32bit calll instruction so that a 32 bit
+ *     return address is pushed.
+ *
+ * All registers are preserved, %ss:%esp will point to the same
+ * place as %ss:%sp did, although the actual value of %esp might
+ * be changed.
+ *
+ * Interrupts are disabled while we are in 32bit mode to save us
+ * having to setup a different IDT.  This code is only used during
+ * the boot process and it doesn't use any interrupts.
+ */
+ENTRY(real_to_prot)
+       .code16
+       pushl   %eax
+       cli
+
+       lgdt    %cs:gdtarg              /* Global descriptor table */
+
+       movl    %cr0, %eax
+       or      $CR0_PE, %ax
+       movl    %eax, %cr0              /* Enter 'protected mode' */
+
+       ljmp    $bootcodeseg, $1f       /* Jump into a 32bit segment */
+1:
+
+       .code32
+       /*  Set all the segment registers to map the same area as the code */
+       mov     $bootdataseg, %eax
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %ss
+       addl    stkdif, %esp            /* Allow for real %ss != %ds */
+
+       popl    %eax
+       ret
+
+/*
+ * prot_to_real()
+ *
+ * Switch CPU back to 16bit real mode in order to call system bios functions.
+ *
+ * All registers are preserved, except that %sp may be changed so that
+ * %ss:%sp points to the same memory.
+ * Note that %ebp is preserved and will not reference the correct part
+ * of the stack.
+ *
+ * Interrupts are enabled while in real mode.
+ *
+ * Based on the descripton in section 14.5 of the 80386 Programmer's
+ * reference book.
+ */
+/*
+ * EPIA_HACK
+ *
+ * VIA C3 processors (Eden, Samuel 2) don't seem to correctly switch back to
+ * executing 16 bit code after the switch to real mode and subsequent jump.
+ *
+ * It is speculated that the CPU is prefetching and decoding branch
+ * targets and not invalidating this buffer on the long jump.
+ * Further investication indicates that the caching of return addresses
+ * is most likely the problem.
+ *
+ * Previous versions just used some extra call/ret and a few NOPs, these
+ * only helped a bit, but booting compressed kernels would still fail.
+ *
+ * Trashing the return address stack (by doing 'call' without matched 'ret')
+ * Seems to fix things completely. 1 iteration isn't enough, 16 is plenty.
+ */
+ENTRY(prot_to_real)
+       .code32
+       pushl   %eax
+#ifdef EPIA_HACK
+       push    %ecx
+       push    $0x10
+       pop     %ecx
+1:     call    trash_return_cache
+       loop    1b
+       pop     %ecx
+#endif
+
+       /*
+        * Load the segment registers while still in protected mode.
+        * Otherwise the control bits don't get changed.
+        * The correct base addresses are loaded later.
+        */
+       movw    $bootrealdata, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %ss
+
+       /*
+        * Load %cs with a segment that has the correct attributes for
+        * 16bit operation.
+        */
+       ljmp    $bootrealseg, $1f
+1:
+
+       .code16
+       movl    %cr0, %eax
+       and     $~CR0_PE, %eax
+       movl    %eax, %cr0              /* Disable potected mode */
+
+       /* Jump far indirect to load real mode %cs */
+       ljmp    *%cs:toreal
+xreal:
+       /*
+        * CPU is now in real mode, load the other segment registers
+        * with their correct base addresses.
+        */
+       mov     %cs, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+       /*
+        * If stack was above 64k, 16bit %ss needs to be different from
+        * 32bit %ss (and the other segment registers).
+        */
+       mov     stkseg, %ax
+       mov     %ax, %ss
+       subl    stkdif, %esp
+
+       /* Check we are returning to an address below 64k */
+       push    %bp
+       movw    %sp, %bp
+       movw    2/*bp*/ + 4/*eax*/ + 2(%bp), %ax        /* high bits ret addr */
+       test    %ax, %ax
+       jne     1f
+       pop     %bp
+
+       sti
+       popl    %eax
+       retl
+
+1:     movw    $3f, %si
+       call    message
+       movl    2/*bp*/ + 4/*eax*/(%bp), %eax           /*  return address */
+       call    dump_eax
+       int     $0x18
+2:     sti
+       hlt
+       jmp     2b
+3:     .asciz  "prot_to_real can't return to "
+
+       .global dump_eax_buff
+dump_eax_buff:
+       . = . + 16
+
+#ifdef EPIA_HACK
+trash_return_cache:
+       .code32
+       pop     %eax
+       jmp     *%eax
+#endif
+
+/* vtophys(void *)
+ * convert boot time 'linear' address to a physical one
+ */
+
+ENTRY(vtophys)
+       .code32
+       xorl    %eax, %eax
+       movw    ourseg, %ax
+       shll    $4, %eax
+       addl    4(%esp), %eax
+       ret
diff --git a/sys/arch/i386/stand/lib/startprog.S b/sys/arch/i386/stand/lib/startprog.S
new file mode 100644 (file)
index 0000000..bd6576a
--- /dev/null
@@ -0,0 +1,110 @@
+/*     $NetBSD: startprog.S,v 1.3 2003/02/01 14:48:18 dsl Exp $        */
+       
+/* starts program in protected mode / flat space
+ with given stackframe
+ needs global variables flatcodeseg and flatdataseg
+ (gdt offsets)
+  derived from: NetBSD:sys/arch/i386/boot/asm.S
+ */
+
+/*
+ * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
+ *
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+  Copyright 1988, 1989, 1990, 1991, 1992 
+   by Intel Corporation, Santa Clara, California.
+
+                All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <machine/asm.h>
+
+/*
+ * startprog(phyaddr,argc,argv,stack)
+ *     start the program on protected mode where phyaddr is the entry point
+ */
+ENTRY(startprog)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       # prepare a new stack
+       movl    $flatdataseg, %ebx
+       movw    %bx, %es                # for arg copy
+       movl    20(%ebp), %eax  # stack
+       subl    $4,%eax
+       movl    %eax, %edi
+       
+       # push some number of args onto the stack
+       movl    12(%ebp), %ecx          # argc
+
+       movl    %ecx, %eax
+       decl    %eax
+       shl     $2, %eax
+       addl    16(%ebp), %eax  # ptr to last arg
+       movl    %eax, %esi
+
+       std                     # backwards
+       rep
+       movsl
+
+       cld             # LynxOS depends on it
+
+       movl    8(%ebp), %ecx   # entry
+
+       # set new stackptr (movsl decd sp 1 more -> dummy return address)
+       movw    %bx, %ss
+       movl    %edi, %esp
+
+       # push on our entry address
+       movl    $flatcodeseg, %ebx              # segment
+       pushl   %ebx
+       pushl   %ecx                    #entry
+
+       # convert over the other data segs
+       movl    $flatdataseg, %ebx
+       mov     %bx, %ds
+       mov     %bx, %es
+
+       # convert the PC (and code seg)
+       lret
diff --git a/sys/arch/i386/stand/lib/test/Makefile.satest b/sys/arch/i386/stand/lib/test/Makefile.satest
new file mode 100644 (file)
index 0000000..ef66abd
--- /dev/null
@@ -0,0 +1,36 @@
+# $NetBSD: Makefile.satest,v 1.2 1999/02/19 19:53:01 drochner Exp $
+
+I386_STAND_DIR?= $S/arch/i386/stand
+
+.PATH: ${I386_STAND_DIR}/lib/test ${I386_STAND_DIR}/lib ${I386_STAND_DIR}/libsa
+
+SRCS+= stand_user.c
+
+# Separate libsa's namespace from userland libraries.
+# Should comply to "sanamespace.h".
+CPPFLAGS+= -Dmain=samain -Dexit=saexit -Dfree=safree
+CPPFLAGS+= -Dopen=saopen -Dclose=saclose -Dread=saread -Dwrite=sawrite
+CPPFLAGS+= -Dioctl=saioctl -Dlseek=salseek
+CPPFLAGS+= -Dprintf=saprintf -Dsprintf=sasprintf -Dvprintf=savprintf
+CPPFLAGS+= -Dputchar=saputchar -Dgets=sagets
+CPPFLAGS+= -Dstrerror=sastrerror  -Derrno=saerrno
+
+CPPFLAGS+= -I$S/lib/libsa -I${I386_STAND_DIR}/libsa -I${I386_STAND_DIR}/lib
+CPPFLAGS+= -I${I386_STAND_DIR}/lib/test -I$S
+
+CPPFLAGS+= -DHEAP_VARIABLE
+
+CFLAGS= -O -g -Wall -fwritable-strings
+
+LDFLAGS= -g -static -Xlinker -M
+LDADD= ${LIBSA} -lz -lkvm -li386 >${PROG}.list 2>&1
+CLEANFILES+= ${PROG}.list
+
+.include <bsd.prog.mk>
+
+### find out what to use for libsa
+SA_AS=         library
+.include "${S}/lib/libsa/Makefile.inc"
+LIBSA=         ${SALIB}
+
+${PROG}: ${LIBSA}
diff --git a/sys/arch/i386/stand/lib/test/biosdisk_user.c b/sys/arch/i386/stand/lib/test/biosdisk_user.c
new file mode 100644 (file)
index 0000000..6ae1071
--- /dev/null
@@ -0,0 +1,135 @@
+/*     $NetBSD: biosdisk_user.c,v 1.7 2008/12/14 18:46:33 christos Exp $       */
+
+/*
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sanamespace.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+
+#include "biosdisk_ll.h"
+#include "biosdisk_user.h"
+
+/*
+ * Replacement for i386/stand/lib/bios_disk.S.
+ * Allows to map BIOS-like device numbers to character
+ * device nodes or plain files.
+ * The actual mapping is defined in the external table
+ * "emuldisktab".
+ */
+
+static int currentdev, currentdte;
+static int fd = -1;
+
+int
+get_diskinfo(int dev)
+{
+       int i, retval;
+
+       if (fd != -1) {
+               close(fd);
+               fd = -1;
+       }
+
+       i = 0;
+       for (;;) {
+               if (emuldisktab[i].biosdev == -1)
+                       break;
+               if (emuldisktab[i].biosdev == dev)
+                       goto ok;
+               i++;
+       }
+       warnx("unknown device %x", dev);
+       return 0; /* triggers error in set_geometry() */
+
+ok:
+       fd = open(emuldisktab[i].name, O_RDONLY, 0);
+       if (fd < 0) {
+               warn("open %s", emuldisktab[i].name);
+               return 0;
+       }
+
+       currentdev = dev;
+       currentdte = i;
+
+       retval = ((emuldisktab[i].cyls - 1) & 0xff) << 16;
+       retval |= ((emuldisktab[i].cyls - 1) & 0x300) << 6;
+       retval |= emuldisktab[i].spt << 8;
+       retval |= emuldisktab[i].heads - 1;
+       return retval;
+}
+
+int
+biosread(int dev, int cyl, int head, int sec, int nsec, char *buf)
+{
+
+       if (dev != currentdev) {
+               warnx("biosread: unexpected device %x", dev);
+               return -1;
+       }
+
+       if (lseek(fd, ((cyl * emuldisktab[currentdte].heads + head)
+                      * emuldisktab[currentdte].spt + sec) * 512,
+                 SEEK_SET) == -1) {
+               warn("lseek");
+               return -1;
+       }
+       if (read(fd, buf, nsec * 512) != nsec * 512) {
+               warn("read");
+               return -1;
+       }
+       return 0;
+}
+
+int
+int13_extension(int dev)
+{
+
+       return 0;
+}
+
+void
+int13_getextinfo(int dev, struct biosdisk_ext13info *info)
+{
+}
+
+struct ext {
+       int8_t  size;
+       int8_t  resvd;
+       int16_t cnt;
+       int16_t off;
+       int16_t seg;
+       int64_t sec;
+};
+
+int
+biosextread(int dev, struct ext *ext)
+{
+       return -1;
+}
diff --git a/sys/arch/i386/stand/lib/test/biosdisk_user.h b/sys/arch/i386/stand/lib/test/biosdisk_user.h
new file mode 100644 (file)
index 0000000..3f4d8f5
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD: biosdisk_user.h,v 1.4 2005/12/11 12:17:49 christos Exp $       */
+
+/*
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Defines a mapping from device numbers to file
+ * names and geometry data. The table must be terminated
+ * by an entry with "biosdev" == -1.
+ */
+
+struct emuldisktabentry {
+       int biosdev;
+       char *name;
+       int spt, heads, cyls;
+};
+
+extern struct emuldisktabentry emuldisktab[];
+
+#if 0
+This is an example:
+struct emuldisktabentry emuldisktab[] = {
+       {0, "/dev/rfd0a", 18, 2, 80},
+       {1, "fdimage", 18, 2, 80},
+       {0x80, "/dev/rwd0d", 100, 4, 1000},
+       {0x81, "hdimage", 100, 4, 1000},
+       {-1}
+};
+#endif
diff --git a/sys/arch/i386/stand/lib/test/ether_bpf.c b/sys/arch/i386/stand/lib/test/ether_bpf.c
new file mode 100644 (file)
index 0000000..4fe7537
--- /dev/null
@@ -0,0 +1,216 @@
+/*     $NetBSD: ether_bpf.c,v 1.10 2008/12/14 18:46:33 christos Exp $  */
+
+/*
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sanamespace.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+
+#include <netif/netif_small.h>
+#include <netif/etherdrv.h>
+
+#define BPFDEV "/dev/bpf0"
+
+#define MAXPKT 1536
+
+/*
+ * Allows to use any configured interface with
+ * standalone network code. Provides the interface used
+ * by i386/stand/lib/netif/netif_small.c.
+ */
+
+static int bpf = -1;
+
+static struct nlist nl[] = {
+       {"_ifnet"},
+       {NULL}
+};
+
+int
+EtherInit(char *ha)
+{
+       int res;
+       u_int val;
+       struct ifreq ifr;
+       kvm_t *kvm;
+       char errbuf[_POSIX2_LINE_MAX];
+       struct ifnet_head ifh;
+       struct ifnet *ifp;
+       struct ifaddr *ifap = 0;
+       struct sockaddr_dl *sdlp;
+       int sdllen;
+
+       bpf = open(BPFDEV, O_RDWR, 0);
+       if (bpf < 0) {
+               warn("open %s", BPFDEV);
+               return 0;
+       }
+
+       val = MAXPKT;
+       res = ioctl(bpf, BIOCSBLEN, &val);
+       if (res < 0) {
+               warn("ioctl BIOCSBLEN");
+               return 0;
+       }
+
+       val = 1;
+       res = ioctl(bpf, BIOCIMMEDIATE, &val);
+       if (res < 0) {
+               warn("ioctl BIOCIMMEDIATE");
+               return 0;
+       }
+
+       val = 1;
+       res = ioctl(bpf, FIONBIO, &val);
+       if (res < 0) {
+               warn("ioctl FIONBIO");
+               return 0;
+       }
+
+       memcpy(ifr.ifr_name, BPF_IFNAME, IFNAMSIZ);
+       res = ioctl(bpf, BIOCSETIF, &ifr);
+       if (res < 0) {
+               warn("ioctl BIOCSETIF %s", BPF_IFNAME);
+               return 0;
+       }
+
+       kvm = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
+       if (!kvm) {
+               warnx(errbuf);
+               return 0;
+       }
+       if (kvm_nlist(kvm, nl) < 0) {
+               warnx("nlist failed (%s)", kvm_geterr(kvm));
+               kvm_close(kvm);
+               return 0;
+       }
+
+       kvm_read(kvm, nl[0].n_value, &ifh, sizeof(struct ifnet_head));
+       ifp = TAILQ_FIRST(&ifh);
+       while (ifp) {
+               struct ifnet ifnet;
+               kvm_read(kvm, (u_long)ifp, &ifnet, sizeof(struct ifnet));
+               if (!strcmp(ifnet.if_xname, BPF_IFNAME)) {
+                       ifap = IFADDR_FIRST(&ifnet);
+                       break;
+               }
+               ifp = IFNET_NEXT(&ifnet);
+       }
+       if (!ifp) {
+               warnx("interface not found");
+               kvm_close(kvm);
+               return 0;
+       }
+
+#define _offsetof(t, m) ((int)((void *)&((t *)0)->m))
+       sdllen = _offsetof(struct sockaddr_dl,
+                          sdl_data[0]) + strlen(BPF_IFNAME) + 6;
+       sdlp = malloc(sdllen);
+
+       while (ifap) {
+               struct ifaddr ifaddr;
+               kvm_read(kvm, (u_long)ifap, &ifaddr, sizeof(struct ifaddr));
+               kvm_read(kvm, (u_long)ifaddr.ifa_addr, sdlp, sdllen);
+               if (sdlp->sdl_family == AF_LINK) {
+                       memcpy(ha, CLLADDR(sdlp), 6);
+                       break;
+               }
+               ifap = IFADDR_NEXT(&ifaddr);
+       }
+       free(sdlp);
+       kvm_close(kvm);
+       if (!ifap) {
+               warnx("interface hw addr not found");
+               return 0;
+       }
+       return 1;
+}
+
+void
+EtherStop(void)
+{
+
+       if (bpf != -1)
+               close(bpf);
+}
+
+int
+EtherSend(char *pkt, int len)
+{
+
+       if (write(bpf, pkt, len) != len) {
+               warn("EtherSend");
+               return -1;
+       }
+       return len;
+}
+
+static union {
+       struct bpf_hdr h;
+       u_char buf[MAXPKT];
+} rbuf;
+
+int
+EtherReceive(char *pkt, int maxlen)
+{
+       int res;
+
+       res = read(bpf, &rbuf, MAXPKT);
+       if (res > 0) {
+#if 0
+               int i;
+               fprintf(stderr, "got packet, len=%d\n", rbuf.h.bh_caplen);
+               if (rbuf.h.bh_caplen < rbuf.h.bh_datalen)
+                       printf("(truncated)\n");
+               for (i = 0; i < 20; i++)
+                       fprintf(stderr, "%02x ", rbuf.buf[rbuf.h.bh_hdrlen + i]);
+               fprintf(stderr, "\n");
+#endif
+               if (rbuf.h.bh_caplen > maxlen)
+                       return 0;
+               memcpy(pkt, &rbuf.buf[rbuf.h.bh_hdrlen], rbuf.h.bh_caplen);
+               return rbuf.h.bh_caplen;
+       }
+
+       return 0;
+}
diff --git a/sys/arch/i386/stand/lib/test/pci_user.c b/sys/arch/i386/stand/lib/test/pci_user.c
new file mode 100644 (file)
index 0000000..57a3c7b
--- /dev/null
@@ -0,0 +1,101 @@
+/*     $NetBSD: pci_user.c,v 1.4 2008/12/14 18:46:33 christos Exp $    */
+
+/*
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sanamespace.h"
+
+#include <sys/types.h>
+#include <machine/pio.h>
+
+#include <pcivar.h>
+
+extern int mapio(void);
+
+/*
+ * Replacement for i386/stand/lib/biospci.c.
+ * Very simple functions to access PCI config space from
+ * userland. Works with configuration mode 1 only, can
+ * only access bus number 0.
+ */
+
+#define        PCI_MODE1_ENABLE        0x80000000UL
+#define        PCI_MODE1_ADDRESS_REG   0x0cf8
+#define        PCI_MODE1_DATA_REG      0x0cfc
+
+static int
+maketag(int bus, int dev, int fcn)
+{
+
+       return PCI_MODE1_ENABLE |
+           (bus << 16) | (dev << 11) | (fcn << 8);
+}
+
+int
+pcicheck(void)
+{
+
+       return mapio() ? -1 : 0;
+}
+
+int
+pcifinddev(int vid, int did, pcihdl_t *handle)
+{
+       int i;
+
+       for (i = 0; i < 32; i++) {
+               pcihdl_t h;
+               int id;
+               h = maketag(0, i, 0);
+               pcicfgread(&h, 0, &id);
+               if (id == (vid | (did << 16))) {
+                       *handle = h;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+int
+pcicfgread(pcihdl_t *handle, int off, int *val)
+{
+       int data;
+
+       outl(PCI_MODE1_ADDRESS_REG, *handle | off);
+       data = inl(PCI_MODE1_DATA_REG);
+       outl(PCI_MODE1_ADDRESS_REG, 0);
+       *val = data;
+       return 0;
+}
+
+int
+pcicfgwrite(pcihdl_t *handle, int off, int val)
+{
+       outl(PCI_MODE1_ADDRESS_REG, *handle | off);
+       outl(PCI_MODE1_DATA_REG, val);
+       outl(PCI_MODE1_ADDRESS_REG, 0);
+       return 0;
+}
diff --git a/sys/arch/i386/stand/lib/test/sanamespace.h b/sys/arch/i386/stand/lib/test/sanamespace.h
new file mode 100644 (file)
index 0000000..41264a5
--- /dev/null
@@ -0,0 +1,20 @@
+/*     $NetBSD: sanamespace.h,v 1.1 1998/05/15 17:07:16 drochner Exp $ */
+
+/* take back the namespace mangling done by "Makefile.satest" */
+
+#undef main
+#undef exit
+#undef free
+#undef open
+#undef close
+#undef read
+#undef write
+#undef ioctl
+#undef lseek
+#undef printf
+#undef sprintf
+#undef vprintf
+#undef putchar
+#undef gets
+#undef strerror
+#undef errno
diff --git a/sys/arch/i386/stand/lib/test/stand_user.c b/sys/arch/i386/stand/lib/test/stand_user.c
new file mode 100644 (file)
index 0000000..c31f1d6
--- /dev/null
@@ -0,0 +1,143 @@
+/*     $NetBSD: stand_user.c,v 1.6 2008/12/14 18:46:33 christos Exp $  */
+
+/*
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <lib/libsa/stand.h>
+
+#include "sanamespace.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <machine/sysarch.h>
+#include <err.h>
+
+/*
+ * Harness for test of standalone code in user space.
+ * XXX Requires silly namespace games.
+ */
+
+#ifndef HEAPSIZE
+#define HEAPSIZE (128*1024)
+#endif
+
+int samain(void);
+
+int
+main(void)
+{
+       char *h = malloc(HEAPSIZE);
+       setheap(h, h + HEAPSIZE);
+
+       return samain();
+}
+
+void
+_rtt(void)
+{
+       warnx("_rtt called");
+       _exit(1);
+}
+
+int
+getsecs(void)
+{
+       struct timeval t;
+       gettimeofday(&t, 0);
+       return t.tv_sec;
+}
+
+void
+delay(int t)
+{
+       struct timeval to;
+       to.tv_sec = 0;
+       to.tv_usec = t;
+       select(0, 0, 0, 0, &to);
+}
+
+/* make output appear unbuffered */
+void
+saputchar(int c)
+{
+       putchar(c);
+       fflush(stdout);
+}
+
+/*
+ * some functions to get access to the hardware
+ */
+
+static int memfd, memcnt;
+
+void *
+mapmem(int offset, int len)
+{
+       void *base;
+
+       if (memcnt == 0)
+               memfd = open("/dev/mem", O_RDWR, 0);
+       if (memfd < 0) {
+               warn("open /dev/mem");
+               return 0;
+       }
+       base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+                   memfd, offset);
+       if (base == (void *)-1) {
+               warn("mmap %x-%x", offset, offset + len - 1);
+               return 0;
+       }
+       memcnt++;
+       return base;
+}
+
+void
+unmapmem(void *addr, int len)
+{
+
+       munmap(addr, len);
+       memcnt--;
+       if (memcnt == 0)
+               close(memfd);
+}
+
+int
+mapio(void)
+{
+       int res;
+
+       res = i386_iopl(1);
+       if (res)
+               warn("i386_iopl");
+       return res;
+}
+
+int ourseg = 12345;
diff --git a/sys/arch/i386/stand/lib/vbe.c b/sys/arch/i386/stand/lib/vbe.c
new file mode 100644 (file)
index 0000000..e2141bf
--- /dev/null
@@ -0,0 +1,419 @@
+/* $NetBSD: vbe.c,v 1.7 2011/02/09 04:37:54 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * VESA BIOS Extensions routines
+ */
+
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#include <machine/bootinfo.h>
+#include "libi386.h"
+#include "vbe.h"
+
+extern const uint8_t rasops_cmap[];
+static uint8_t *vbe_edid = NULL;
+static int vbe_edid_valid = 0;
+
+static struct _vbestate {
+       int             available;
+       int             modenum;
+} vbestate;
+
+static int
+vbe_mode_is_supported(struct modeinfoblock *mi)
+{
+       if ((mi->ModeAttributes & 0x01) == 0)
+               return 0;       /* mode not supported by hardware */
+       if ((mi->ModeAttributes & 0x08) == 0)
+               return 0;       /* linear fb not available */
+       if ((mi->ModeAttributes & 0x10) == 0)
+               return 0;       /* text mode */
+       if (mi->NumberOfPlanes != 1)
+               return 0;       /* planar mode not supported */
+       if (mi->MemoryModel != 0x04 /* Packed pixel */ &&
+           mi->MemoryModel != 0x06 /* Direct Color */)
+               return 0;       /* unsupported pixel format */
+       return 1;
+}
+
+static bool
+vbe_check(void)
+{
+       if (!vbestate.available) {
+               printf("VBE not available\n");
+               return false;
+       }
+       return true;
+}
+
+void
+vbe_init(void)
+{
+       struct vbeinfoblock vbe;
+
+       memset(&vbe, 0, sizeof(vbe));
+       memcpy(vbe.VbeSignature, "VBE2", 4);
+       if (biosvbe_info(&vbe) != 0x004f)
+               return;
+       if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
+               return;
+
+       vbestate.available = 1;
+       vbestate.modenum = 0;
+}
+
+int
+vbe_available(void)
+{
+       return vbestate.available;
+}
+
+int
+vbe_set_palette(const uint8_t *cmap, int slot)
+{
+       struct paletteentry pe;
+       int ret;
+
+       if (!vbe_check())
+               return 1;
+
+       pe.Blue = cmap[2] >> 2;
+       pe.Green = cmap[1] >> 2;
+       pe.Red = cmap[0] >> 2;
+       pe.Alignment = 0;
+
+       ret = biosvbe_palette_data(0x0600, slot, &pe);
+
+       return ret == 0x004f ? 0 : 1;
+}
+
+int
+vbe_set_mode(int modenum)
+{
+       struct modeinfoblock mi;
+       struct btinfo_framebuffer fb;
+       int ret, i;
+
+       if (!vbe_check())
+               return 1;
+
+       ret = biosvbe_get_mode_info(modenum, &mi);
+       if (ret != 0x004f) {
+               printf("mode 0x%x invalid\n", modenum);
+               return 1;
+       }
+
+       if (!vbe_mode_is_supported(&mi)) {
+               printf("mode 0x%x not supported\n", modenum);
+               return 1;
+       }
+
+       ret = biosvbe_set_mode(modenum);
+       if (ret != 0x004f) {
+               printf("mode 0x%x could not be set\n", modenum);
+               return 1;
+       }
+
+       /* Setup palette for packed pixel mode */
+       if (mi.MemoryModel == 0x04)
+               for (i = 0; i < 256; i++)
+                       vbe_set_palette(&rasops_cmap[i * 3], i);
+
+       fb.physaddr = (uint64_t)mi.PhysBasePtr & 0xffffffff;
+       fb.width = mi.XResolution;
+       fb.height = mi.YResolution;
+       fb.stride = mi.BytesPerScanLine;
+       fb.depth = mi.BitsPerPixel;
+       fb.flags = 0;
+       fb.rnum = mi.RedMaskSize;
+       fb.rpos = mi.RedFieldPosition;
+       fb.gnum = mi.GreenMaskSize;
+       fb.gpos = mi.GreenFieldPosition;
+       fb.bnum = mi.BlueMaskSize;
+       fb.bpos = mi.BlueFieldPosition;
+       fb.vbemode = modenum;
+
+       framebuffer_configure(&fb);
+
+       return 0;
+}
+
+int
+vbe_commit(void)
+{
+       int ret = 1;
+
+       if (vbestate.modenum > 0) {
+               ret = vbe_set_mode(vbestate.modenum);
+               if (ret) {
+                       printf("WARNING: failed to set VBE mode 0x%x\n",
+                           vbestate.modenum);
+                       wait_sec(5);
+               }
+       }
+       return ret;
+}
+
+static void *
+vbe_farptr(uint32_t farptr)
+{
+       return VBEPHYPTR((((farptr & 0xffff0000) >> 12) + (farptr & 0xffff)));
+}
+
+static int
+vbe_parse_mode_str(char *str, int *x, int *y, int *depth)
+{
+       char *p;
+
+       p = str;
+       *x = strtoul(p, NULL, 0);
+       if (*x == 0)
+               return 0;
+       p = strchr(p, 'x');
+       if (!p)
+               return 0;
+       ++p;
+       *y = strtoul(p, NULL, 0);
+       if (*y == 0)
+               return 0;
+       p = strchr(p, 'x');
+       if (!p)
+               *depth = 8;
+       else {
+               ++p;
+               *depth = strtoul(p, NULL, 0);
+               if (*depth == 0)
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int
+vbe_find_mode_xyd(int x, int y, int depth)
+{
+       struct vbeinfoblock vbe;
+       struct modeinfoblock mi;
+       uint32_t farptr;
+       uint16_t mode;
+       int safety = 0;
+
+       memset(&vbe, 0, sizeof(vbe));
+       memcpy(vbe.VbeSignature, "VBE2", 4);
+       if (biosvbe_info(&vbe) != 0x004f)
+               return 0;
+       if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
+               return 0;
+       farptr = vbe.VideoModePtr;
+       if (farptr == 0)
+               return 0;
+
+       while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
+               safety++;
+               farptr += 2;
+               if (safety == 100)
+                       return 0;
+               if (biosvbe_get_mode_info(mode, &mi) != 0x004f)
+                       continue;
+               /* we only care about linear modes here */
+               if (vbe_mode_is_supported(&mi) == 0)
+                       continue;
+               safety = 0;
+               if (mi.XResolution == x &&
+                   mi.YResolution == y &&
+                   mi.BitsPerPixel == depth)
+                       return mode;
+       }
+
+       return 0;
+}
+
+static int
+vbe_find_mode(char *str)
+{
+       int x, y, depth;
+
+       if (!vbe_parse_mode_str(str, &x, &y, &depth))
+               return 0;
+
+       return vbe_find_mode_xyd(x, y, depth);
+}
+
+static void
+vbe_dump_mode(int modenum, struct modeinfoblock *mi)
+{
+       printf("0x%x=%dx%dx%d", modenum,
+           mi->XResolution, mi->YResolution, mi->BitsPerPixel);
+}
+
+static int
+vbe_get_edid(int *pwidth, int *pheight)
+{
+       const uint8_t magic[] = EDID_MAGIC;
+       int ddc_caps, ret;
+
+       ddc_caps = biosvbe_ddc_caps();
+       if (ddc_caps == 0) {
+               return 1;
+       }
+
+       if (vbe_edid == NULL) {
+               vbe_edid = alloc(128);
+       }
+       if (vbe_edid_valid == 0) {
+               ret = biosvbe_ddc_read_edid(0, vbe_edid);
+               if (ret != 0x004f)
+                       return 1;
+               if (memcmp(vbe_edid, magic, sizeof(magic)) != 0)
+                       return 1;
+               vbe_edid_valid = 1;
+       }
+
+       *pwidth = vbe_edid[EDID_DESC_BLOCK + 2] |
+           (((int)vbe_edid[EDID_DESC_BLOCK + 4] & 0xf0) << 4);
+       *pheight = vbe_edid[EDID_DESC_BLOCK + 5] |
+           (((int)vbe_edid[EDID_DESC_BLOCK + 7] & 0xf0) << 4);
+
+       return 0;
+}
+
+void
+vbe_modelist(void)
+{
+       struct vbeinfoblock vbe;
+       struct modeinfoblock mi;
+       uint32_t farptr;
+       uint16_t mode;
+       int nmodes = 0, safety = 0;
+       int ddc_caps, edid_width, edid_height;
+
+       if (!vbe_check())
+               return;
+
+       ddc_caps = biosvbe_ddc_caps();
+       if (ddc_caps & 3) {
+               printf("DDC");
+               if (ddc_caps & 1)
+                       printf(" [DDC1]");
+               if (ddc_caps & 2)
+                       printf(" [DDC2]");
+
+               if (vbe_get_edid(&edid_width, &edid_height) != 0)
+                       printf(": no EDID information\n");
+               else
+                       printf(": EDID %dx%d\n", edid_width, edid_height);
+       }
+
+       printf("Modes: ");
+       memset(&vbe, 0, sizeof(vbe));
+       memcpy(vbe.VbeSignature, "VBE2", 4);
+       if (biosvbe_info(&vbe) != 0x004f)
+               goto done;
+       if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
+               goto done;
+       farptr = vbe.VideoModePtr;
+       if (farptr == 0)
+               goto done;
+
+       while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
+               safety++;
+               farptr += 2;
+               if (safety == 100) {
+                       printf("[?] ");
+                       break;
+               }
+               if (biosvbe_get_mode_info(mode, &mi) != 0x004f)
+                       continue;
+               /* we only care about linear modes here */
+               if (vbe_mode_is_supported(&mi) == 0)
+                       continue;
+               safety = 0;
+               if (nmodes % 4 == 0)
+                       printf("\n");
+               else
+                       printf("  ");
+               vbe_dump_mode(mode, &mi);
+               nmodes++;
+       }
+
+done:
+       if (nmodes == 0)
+               printf("none found");
+       printf("\n");
+}
+
+void
+command_vesa(char *cmd)
+{
+       char arg[20];
+       int modenum, edid_width, edid_height;
+
+       if (!vbe_check())
+               return;
+
+       strlcpy(arg, cmd, sizeof(arg));
+
+       if (strcmp(arg, "list") == 0) {
+               vbe_modelist();
+               return;
+       }
+
+       if (strcmp(arg, "disabled") == 0 || strcmp(arg, "off") == 0) {
+               vbestate.modenum = 0;
+               return;
+       }
+
+       if (strcmp(arg, "enabled") == 0 || strcmp(arg, "on") == 0) {
+               if (vbe_get_edid(&edid_width, &edid_height) != 0) {
+                       modenum = VBE_DEFAULT_MODE;
+               } else {
+                       modenum = vbe_find_mode_xyd(edid_width, edid_height, 8);
+                       if (modenum == 0)
+                               modenum = VBE_DEFAULT_MODE;
+               }
+       } else if (strncmp(arg, "0x", 2) == 0) {
+               modenum = strtoul(arg, NULL, 0);
+       } else if (strchr(arg, 'x') != NULL) {
+               modenum = vbe_find_mode(arg);
+               if (modenum == 0) {
+                       printf("mode %s not supported by firmware\n", arg);
+                       return;
+               }
+       } else {
+               modenum = 0;
+       }
+
+       if (modenum >= 0x100) {
+               vbestate.modenum = modenum;
+               return;
+       }
+
+       printf("invalid flag, must be 'on', 'off', "
+           "a display mode, or a VBE mode number\n");
+}
diff --git a/sys/arch/i386/stand/lib/vbe.h b/sys/arch/i386/stand/lib/vbe.h
new file mode 100644 (file)
index 0000000..2476cbc
--- /dev/null
@@ -0,0 +1,112 @@
+/* $NetBSD: vbe.h,v 1.3 2011/02/09 04:37:54 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define VBE_DEFAULT_MODE       0x101   /* 640x480x8 */
+
+struct vbeinfoblock {
+       char VbeSignature[4];
+       uint16_t VbeVersion;
+       uint32_t OemStringPtr;
+       uint32_t Capabilities;
+       uint32_t VideoModePtr;
+       uint16_t TotalMemory;
+       uint16_t OemSoftwareRev;
+       uint32_t OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
+       /* data area, in total max 512 bytes for VBE 2.0 */
+       uint8_t Reserved[222];
+       uint8_t OemData[256];
+} __packed;
+
+struct modeinfoblock {
+       /* Mandatory information for all VBE revisions */
+       uint16_t ModeAttributes;
+       uint8_t WinAAttributes, WinBAttributes;
+       uint16_t WinGranularity, WinSize, WinASegment, WinBSegment;
+       uint32_t WinFuncPtr;
+       uint16_t BytesPerScanLine;
+       /* Mandatory information for VBE 1.2 and above */
+       uint16_t XResolution, YResolution;
+       uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
+       uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
+       uint8_t Reserved1;
+       /* Direct Color fields
+          (required for direct/6 and YUV/7 memory models) */
+       uint8_t RedMaskSize, RedFieldPosition;
+       uint8_t GreenMaskSize, GreenFieldPosition;
+       uint8_t BlueMaskSize, BlueFieldPosition;
+       uint8_t RsvdMaskSize, RsvdFieldPosition;
+       uint8_t DirectColorModeInfo;
+       /* Mandatory information for VBE 2.0 and above */
+       uint32_t PhysBasePtr;
+       uint32_t OffScreenMemOffset;    /* reserved in VBE 3.0 and above */
+       uint16_t OffScreenMemSize;      /* reserved in VBE 3.0 and above */
+
+       /* Mandatory information for VBE 3.0 and above */
+       uint16_t LinBytesPerScanLine;
+       uint8_t BnkNumberOfImagePages;
+       uint8_t LinNumberOfImagePages;
+       uint8_t LinRedMaskSize, LinRedFieldPosition;
+       uint8_t LinGreenMaskSize, LinGreenFieldPosition;
+       uint8_t LinBlueMaskSize, LinBlueFieldPosition;
+       uint8_t LinRsvdMaskSize, LinRsvdFieldPosition;
+       uint32_t MaxPixelClock;
+       uint8_t Reserved4[189];
+} __packed;
+
+struct paletteentry {
+       uint8_t Blue;
+       uint8_t Green;
+       uint8_t Red;
+       uint8_t Alignment;
+} __packed;
+
+/* EDID */
+#define        EDID_MAGIC      { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }
+#define        EDID_DESC_BLOCK 0x36
+
+/* low-level VBE calls, from biosvbe.S */
+int biosvbe_info(struct vbeinfoblock *);
+int biosvbe_set_mode(int);
+int biosvbe_get_mode_info(int, struct modeinfoblock *);
+int biosvbe_palette_format(int); 
+int biosvbe_palette_data(int, int, struct paletteentry *);
+int biosvbe_ddc_caps(void);
+int biosvbe_ddc_read_edid(int, void *);
+
+/* high-level VBE helpers, from vbe.c */
+void vbe_init(void);
+int vbe_commit(void);
+int vbe_available(void);
+int vbe_set_mode(int);
+int vbe_set_palette(const uint8_t *, int);
+void vbe_modelist(void);
+
+void command_vesa(char *);
+
+/* adjust physical address; boot code runs with %ds having a 64k offset */
+#define VBEPHYPTR(x)   ((uint8_t *)((x) - (64 * 1024)))
diff --git a/sys/lib/libkern/Makefile b/sys/lib/libkern/Makefile
new file mode 100644 (file)
index 0000000..09e9b6a
--- /dev/null
@@ -0,0 +1,31 @@
+#      $NetBSD: Makefile,v 1.95 2009/01/18 20:42:11 he Exp $
+
+LIB=           kern
+NOPIC=         # defined
+LLIBS=         # defined
+
+.include "Makefile.libkern"
+.ifndef ARCHSUBDIR
+.BEGIN:
+       @echo no ARCHSUBDIR for ${MACHINE_ARCH} nor ${MACHINE_CPU}
+       @false
+.endif
+
+# only needed during build
+libinstall::
+
+.undef DESTDIR
+.include <bsd.lib.mk>
+
+lib${LIB}.o:: ${OBJS}
+       @echo building standard ${LIB} library
+       @rm -f lib${LIB}.o
+       @${LD} -r -o lib${LIB}.o `NM=${NM} ${LORDER} ${OBJS} | ${TSORT}`
+
+lib${LIB}.po:: ${POBJS}
+       @echo building profiled ${LIB} library
+       @rm -f lib${LIB}.po
+       @${LD} -r -o lib${LIB}.po `NM=${NM} ${LORDER} ${POBJS} | ${TSORT}`
+
+showsources: ${SRCS}
+       @echo ${.ALLSRC}
diff --git a/sys/lib/libkern/Makefile.inc b/sys/lib/libkern/Makefile.inc
new file mode 100644 (file)
index 0000000..9fe2db2
--- /dev/null
@@ -0,0 +1,93 @@
+#      $NetBSD: Makefile.inc,v 1.40 2005/12/20 19:35:26 christos Exp $
+#
+#      Configuration variables (default values are below):
+#
+#      S       must be set to the top of the 'sys' tree.
+#      KERNDST may be set to the location of the directory where library
+#              objects are to be built.  Defaults to ${.OBJDIR}/lib/kern.
+#      KERN_AS may be set to 'obj' to build a object from the library's
+#              object files.  (Otherwise, a library will be built.)
+#              Defaults to 'library'.
+#      KERNMISCCPPFLAGS
+#              Miscellaneous cpp flags to be passed to the library's Makefile
+#              when building.
+#      KERNMISCMAKEFLAGS
+#              Miscellaneous flags to be passed to the library's Makefile when
+#              building.  See library's Makefile for more details about
+#              supported flags and their default values.
+
+# Default values:
+KERNDST?=      ${.OBJDIR}/lib/kern
+KERN_AS?=      library
+KERNDOTDIR?= ../../.
+
+KERNDIR=       ${S:S@^.@${KERNDOTDIR}@:Q}/lib/libkern
+.if (${KERN_AS} == "obj")
+KERNLIB=       ${KERNDST}/libkern.o
+KERNLIB_PROF=  ${KERNDST}/libkern.po
+.else
+KERNLIB=       ${KERNDST}/libkern.a
+KERNLIB_PROF=  ${KERNDST}/libkern_p.a
+.endif
+
+LIBKERNLNBN=   llib-lkern.ln
+KERNLIBLN=     ${KERNDST}/${LIBKERNLNBN}
+
+KERNMAKE= \
+       cd ${KERNDST} && ${MAKE} -f ${KERNDIR:Q}/Makefile \
+           KERNDIR=${KERNDIR:Q} \
+           CC=${CC:Q} CFLAGS=${CFLAGS:Q} \
+           AS=${AS:Q} AFLAGS=${AFLAGS:Q} \
+           LORDER=${LORDER:Q} \
+           TSORT=${TSORT:Q} \
+           LD=${LD:Q} STRIP=${STRIP:Q} \
+           AR=${AR:Q} NM=${NM:Q} \
+           RANLIB=${RANLIB:Q} SIZE=${SIZE:Q} \
+           MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \
+           KERNCPPFLAGS=${CPPFLAGS:S@^-I.@-I${KERNDOTDIR}@g:Q} \
+           KERNMISCCPPFLAGS=${KERNMISCCPPFLAGS:Q} \
+           LINTFLAGS=${KERNLINTFLAGS:Q} \
+           ${KERNMISCMAKEFLAGS}
+
+${KERNLIB}:            .NOTMAIN .MAKE __always_make_kernlib
+       @echo making sure the kern library is up to date...
+.if (${KERN_AS} == "library")
+       @${KERNMAKE} libkern.a
+.else
+       @${KERNMAKE} libkern.o
+.endif
+
+${KERNLIB_PROF}:       .NOTMAIN .MAKE __always_make_kernlib
+       @echo making sure the profiled kern library is up to date...
+.if (${KERN_AS} == "library")
+       @${KERNMAKE} libkern_p.a
+.else
+       @${KERNMAKE} libkern.po
+.endif
+
+${KERNLIBLN}:          .NOTMAIN .MAKE __always_make_kernlib
+       @echo making sure the kern lint library is up to date...
+       @${KERNMAKE} ${LIBKERNLNBN}
+
+clean:                 .NOTMAIN cleankernlib
+cleankernlib:          .NOTMAIN
+       @echo cleaning the kern library objects
+       @if [ -d "${KERNDST}" ]; then ${KERNMAKE} clean; fi
+
+cleandir distclean:    .NOTMAIN cleandirkernlib
+cleandirkernlib:       .NOTMAIN
+       @echo cleandiring the kern library objects
+       @if [ -d "${KERNDST}" ]; then ${KERNMAKE} cleandir; fi
+
+dependall depend:      .NOTMAIN dependkernlib
+dependkernlib:         .NOTMAIN .MAKE __always_make_kernlib
+       @echo depending the kern library objects
+       @${KERNMAKE} depend
+
+__always_make_kernlib: .NOTMAIN
+       @(mkdir -p ${KERNDST})
+
+.PHONY: __always_make_kernlib
+.PHONY: cleankernlib cleandirkernlib dependkernlib
+
+.include "${.PARSEDIR}/../../../common/lib/libc/Makefile.inc"
diff --git a/sys/lib/libkern/Makefile.libkern b/sys/lib/libkern/Makefile.libkern
new file mode 100644 (file)
index 0000000..e15c16c
--- /dev/null
@@ -0,0 +1,108 @@
+#      $NetBSD: Makefile.libkern,v 1.15 2011/11/19 22:51:25 tls Exp $
+
+# 
+# Variable definitions for libkern.  
+#
+# Before including this, you _must_ set
+#   KERNDIR: location of sys/lib/libkern
+#
+# You *may* set:
+#   LIBKERN_ARCH: architecture subdir to be used
+#   KERNCPPFLAGS: see Makefile.inc
+#   KERNMISCCPPFLAGS: see Makefile.inc
+#
+
+.include <bsd.own.mk>
+
+.if defined(LIBKERN_ARCH) && !empty(LIBKERN_ARCH) && \
+    exists(${KERNDIR}/arch/${LIBKERN_ARCH})
+ARCHSUBDIR=     ${LIBKERN_ARCH}
+.elif defined(MACHINE_ARCH) && !empty(MACHINE_ARCH) && \
+    exists(${KERNDIR}/arch/${MACHINE_ARCH})
+ARCHSUBDIR=     ${MACHINE_ARCH}
+.elif defined(MACHINE_CPU) && !empty(MACHINE_CPU) && \
+    exists(${KERNDIR}/arch/${MACHINE_CPU})
+ARCHSUBDIR=     ${MACHINE_CPU}
+.endif
+
+M= ${KERNDIR}/arch/${ARCHSUBDIR}
+
+CPPFLAGS+=     -I$M ${KERNCPPFLAGS} ${KERNMISCCPPFLAGS}
+
+.include "${.PARSEDIR}/../../../common/lib/libc/Makefile.inc"
+.include "${.PARSEDIR}/../../../common/lib/libutil/Makefile.inc"
+.include "${.PARSEDIR}/../../../common/lib/libprop/Makefile.inc"
+.include "${.PARSEDIR}/../../../common/lib/libppath/Makefile.inc"
+.include "${.PARSEDIR}/../../../common/lib/libquota/Makefile.inc"
+
+CPPFLAGS+=     -I${KERNDIR}/../../../common/include
+
+.PATH.c: ${KERNDIR}
+.if exists ($M/Makefile.inc)
+.PATH.c: $M
+.PATH.S: $M
+.include "$M/Makefile.inc"
+.endif
+
+.if (${MACHINE_ARCH} != "alpha") && \
+    (${MACHINE_ARCH} != "mips64eb" || !empty(CFLAGS:M-mabi=32)) && \
+    (${MACHINE_ARCH} != "mips64el" || !empty(CFLAGS:M-mabi=32)) && \
+    (${MACHINE_ARCH} != "powerpc64") && \
+    (${MACHINE_ARCH} != "sparc64") && \
+    (${MACHINE_ARCH} != "x86_64" || !empty(CFLAGS:M-m32))
+# Quad support
+SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
+       lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
+       subdi3.c  ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
+.endif
+
+# Other stuff
+SRCS+= kern_assert.c __main.c
+SRCS+= __cmsg_alignbytes.c cpuset.c inet_addr.c intoa.c
+.if empty(SRCS:Mbyte_swap_8.*)
+SRCS+= bswap64.c
+.endif
+SRCS+= md4c.c md5c.c rmd160.c sha1.c sha2.c
+SRCS+= pmatch.c arc4random.c bcd.c mcount.c mertwist.c crc32.c
+
+SRCS+= ppath_kmem_alloc.c
+
+SRCS+= strsep.c strstr.c
+SRCS+= strlcpy.c strlcat.c
+
+SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c
+SRCS+= memcpy.c memmove.c
+SRCS+= strchr.c strrchr.c
+SRCS+= memcmp.c
+.if empty(SRCS:Mmemset2.*)
+SRCS+= memset.c 
+.endif
+SRCS+= popcount32.c popcount64.c
+SRCS+= strtoul.c strtoll.c strtoull.c strtoumax.c
+
+SRCS+= scanc.c skpc.c
+SRCS+= random.c
+SRCS+= rngtest.c
+
+SRCS+= memchr.c
+SRCS+= strcat.c strcmp.c strcpy.c strlen.c
+SRCS+= strncmp.c strncpy.c
+SRCS+= strcasecmp.c strncasecmp.c
+
+SRCS+= xlat_mbr_fstype.c
+
+SRCS+= heapsort.c ptree.c rb.c
+
+# Files to clean up
+CLEANFILES+= lib${LIB}.o lib${LIB}.po
+
+# Remove from SRCS the .c files for any .S files added by the MD makefiles,
+# also remove from SRCS the .c files for the .c files in NO_SRCS.
+# (Unlike libc, we don't worry about lint)
+
+.for check_file in ${SRCS:M*.S} ${NO_SRCS}
+unwanted_file := ${SRCS:M${check_file:.S=.c}}
+.if "${unwanted_file}" != ""
+SRCS := ${SRCS:N${unwanted_file}}
+.endif
+.endfor
diff --git a/sys/lib/libkern/__main.c b/sys/lib/libkern/__main.c
new file mode 100644 (file)
index 0000000..fc0359c
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: __main.c,v 1.6 2009/03/15 21:33:51 cegger Exp $        */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+void __main(void);
+
+void
+__main(void)
+{
+}
diff --git a/sys/lib/libkern/arc4random.c b/sys/lib/libkern/arc4random.c
new file mode 100644 (file)
index 0000000..279c016
--- /dev/null
@@ -0,0 +1,327 @@
+/*     $NetBSD: arc4random.c,v 1.29 2011/11/29 13:16:27 drochner Exp $ */
+
+/*-
+ * Copyright (c) 2002, 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * THE BEER-WARE LICENSE
+ *
+ * <dan@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff.  If we meet some day, and you
+ * think this stuff is worth it, you can buy me a beer in return.
+ *
+ * Dan Moschuk
+ *
+ * $FreeBSD: src/sys/libkern/arc4random.c,v 1.9 2001/08/30 12:30:58 bde Exp $
+ */
+
+#include <sys/cdefs.h>
+
+#ifdef _KERNEL
+#include "rnd.h"
+#else
+#define NRND 0
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/kernel.h>
+#endif
+#include <sys/systm.h>
+
+#ifdef _KERNEL
+#include <sys/mutex.h>
+#include <sys/rngtest.h>
+#else
+#define mutex_spin_enter(x) ;
+#define mutex_spin_exit(x) ;
+#define mutex_init(x, y, z) ;
+#endif
+
+#include <lib/libkern/libkern.h>
+
+#if NRND > 0
+#include <sys/rnd.h>
+#include <dev/rnd_private.h>
+
+static rndsink_t       rs;
+
+#endif
+
+/*
+ * The best known attack that distinguishes RC4 output from a random
+ * bitstream requires 2^25 bytes.  (see Paul and Preneel, Analysis of
+ * Non-fortuitous Predictive States of the RC4 Keystream Generator.
+ * INDOCRYPT 2003, pp52 â€“ 67).
+ *
+ * However, we discard the first 1024 bytes of output, avoiding the
+ * biases detected in this paper.  The best current attack that
+ * can distinguish this "RC4[drop]" output seems to be Fleuhrer &
+ * McGrew's attack which requires 2^30.6 bytes of output:
+ * Fluhrer and McGrew, Statistical Analysis of the Alleged RC4
+ * Keystream Generator. FSE 2000, pp19 â€“ 30
+ *
+ * We begin trying to rekey at 2^24 bytes, and forcibly rekey at 2^29 bytes
+ * even if the resulting key cannot be guaranteed to have full entropy.
+ */
+#define        ARC4_MAXBYTES           (16 * 1024 * 1024)
+#define ARC4_HARDMAX           (512 * 1024 * 1024)
+#define        ARC4_RESEED_SECONDS     300
+#define        ARC4_KEYBYTES           16 /* 128 bit key */
+
+#ifdef _STANDALONE
+#define        time_uptime     1       /* XXX ugly! */
+#endif /* _STANDALONE */
+
+static u_int8_t arc4_i, arc4_j;
+static int arc4_initialized = 0;
+static int arc4_numbytes = 0;
+static u_int8_t arc4_sbox[256];
+static time_t arc4_nextreseed;
+
+#ifdef _KERNEL
+kmutex_t       arc4_mtx;
+#endif
+
+static inline u_int8_t arc4_randbyte(void);
+static inline void arc4randbytes_unlocked(void *, size_t);
+void _arc4randbytes(void *, size_t);
+uint32_t _arc4random(void);
+
+static inline void
+arc4_swap(u_int8_t *a, u_int8_t *b)
+{
+       u_int8_t c;
+
+       c = *a;
+       *a = *b;
+       *b = c;
+}
+
+/*
+ * Stir our S-box.
+ */
+static void
+arc4_randrekey(void *arg)
+{
+       u_int8_t key[256];
+       int n, ask_for_more = 0;
+#ifdef _KERNEL
+#ifdef DIAGNOSTIC
+#if 0  /* XXX rngtest_t is too large and could cause stack overflow */
+       rngtest_t rt;
+#endif
+#endif
+#endif
+#if NRND > 0
+       static int callback_pending;
+       int r;
+#endif
+
+       /*
+        * The first time through, we must take what we can get,
+        * so schedule ourselves for callback no matter what.
+        */
+       if (__predict_true(arc4_initialized)) {
+               mutex_spin_enter(&arc4_mtx);
+       }
+#if NRND > 0   /* XXX without rnd, we will key from the stack, ouch! */
+       else {
+               ask_for_more = 1;
+               r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_ANY);
+               goto got_entropy;
+       }
+
+       if (arg == NULL) {
+               if (callback_pending) {
+                       if (arc4_numbytes > ARC4_HARDMAX) {
+                               printf("arc4random: WARNING, hit 2^29 bytes, "
+                                   "forcibly rekeying.\n");
+                               r = rnd_extract_data(key, ARC4_KEYBYTES,
+                                   RND_EXTRACT_ANY);
+                               rndsink_detach(&rs);
+                               callback_pending = 0;
+                               goto got_entropy;
+                       } else {
+                               mutex_spin_exit(&arc4_mtx);
+                               return;
+                       }
+               }
+               r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_GOOD);
+               if (r < ARC4_KEYBYTES) {
+                       ask_for_more = 1;
+               }
+       } else {
+               ask_for_more = 0;
+               callback_pending = 0;
+               if (rs.len != ARC4_KEYBYTES) {
+                       panic("arc4_randrekey: rekey callback bad length");
+               }
+               memcpy(key, rs.data, rs.len);
+               memset(rs.data, 0, rs.len);
+       }
+
+got_entropy:
+
+       if (!ask_for_more) {
+               callback_pending = 0;
+       } else if (!callback_pending) {
+               callback_pending = 1;
+               strlcpy(rs.name, "arc4random", sizeof(rs.name));
+               rs.cb = arc4_randrekey;
+               rs.arg = &rs;
+               rs.len = ARC4_KEYBYTES;
+               rndsink_attach(&rs);
+       }
+#endif
+       /*
+        * If it's the first time, or we got a good key, actually rekey.
+        */
+       if (!ask_for_more || !arc4_initialized) {
+               for (n = ARC4_KEYBYTES; n < sizeof(key); n++)
+                               key[n] = key[n % ARC4_KEYBYTES];
+
+               for (n = 0; n < 256; n++) {
+                       arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
+                       arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
+               }
+               arc4_i = arc4_j;
+
+               memset(key, 0, sizeof(key));
+               /*
+                * Throw away the first N words of output, as suggested in the
+                * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
+                * by Fluher, Mantin, and Shamir.  (N = 256 in our case.)
+                */
+               for (n = 0; n < 256 * 4; n++)
+                       arc4_randbyte();
+
+               /* Reset for next reseed cycle. */
+               arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS;
+               arc4_numbytes = 0;
+#ifdef _KERNEL
+#ifdef DIAGNOSTIC
+#if 0  /* XXX rngtest_t is too large and could cause stack overflow */
+               /*
+                * Perform the FIPS 140-2 statistical RNG test; warn if our
+                * output has such poor quality as to fail the test.
+                */
+               arc4randbytes_unlocked(rt.rt_b, sizeof(rt.rt_b));
+               strlcpy(rt.rt_name, "arc4random", sizeof(rt.rt_name));
+               if (rngtest(&rt)) {
+                       /* rngtest will scream to the console. */
+                       arc4_nextreseed = time_uptime;
+                       arc4_numbytes = ARC4_MAXBYTES;
+                       /* XXX should keep old context around, *NOT* use new */
+               }
+#endif
+#endif
+#endif
+       }
+       if (__predict_true(arc4_initialized)) {
+               mutex_spin_exit(&arc4_mtx);
+       }
+}
+
+/*
+ * Initialize our S-box to its beginning defaults.
+ */
+static void
+arc4_init(void)
+{
+       int n;
+
+       mutex_init(&arc4_mtx, MUTEX_DEFAULT, IPL_VM);
+       arc4_i = arc4_j = 0;
+       for (n = 0; n < 256; n++)
+               arc4_sbox[n] = (u_int8_t) n;
+
+       arc4_randrekey(NULL);
+       arc4_initialized = 1;
+}
+
+/*
+ * Generate a random byte.
+ */
+static inline u_int8_t
+arc4_randbyte(void)
+{
+       u_int8_t arc4_t;
+
+       arc4_i = (arc4_i + 1) % 256;
+       arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256;
+
+       arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]);
+
+       arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256;
+       return arc4_sbox[arc4_t];
+}
+
+static inline void
+arc4randbytes_unlocked(void *p, size_t len)
+{
+       u_int8_t *buf = (u_int8_t *)p;
+       size_t i;
+
+       for (i = 0; i < len; buf[i] = arc4_randbyte(), i++)
+               continue;
+}
+
+void
+_arc4randbytes(void *p, size_t len)
+{
+       /* Initialize array if needed. */
+       if (!arc4_initialized) {
+               arc4_init();
+               /* avoid conditionalizing locking */
+               return arc4randbytes_unlocked(p, len);
+       }
+       mutex_spin_enter(&arc4_mtx);
+       arc4randbytes_unlocked(p, len);
+       arc4_numbytes += len;
+       mutex_spin_exit(&arc4_mtx);
+       if ((arc4_numbytes > ARC4_MAXBYTES) ||
+           (time_uptime > arc4_nextreseed)) {
+               arc4_randrekey(NULL);
+       }
+}
+
+u_int32_t
+_arc4random(void)
+{
+        u_int32_t ret;
+        u_int8_t *retc;
+
+        retc = (u_int8_t *)&ret;
+
+        _arc4randbytes(retc, sizeof(u_int32_t));
+        return ret;
+}
diff --git a/sys/lib/libkern/arch/alpha/Makefile.inc b/sys/lib/libkern/arch/alpha/Makefile.inc
new file mode 100644 (file)
index 0000000..9372ea4
--- /dev/null
@@ -0,0 +1,54 @@
+#      $NetBSD: Makefile.inc,v 1.28 2009/08/14 19:23:53 dsl Exp $
+
+SRCS+= _mcount.S
+SRCS+= byte_swap_2.S byte_swap_4.S
+SRCS+= ffs.S
+SRCS+= memcpy.S memmove.S
+
+SRCS+= softfloat.c
+
+# `source' files built from m4 source
+SRCS+= __divqu.S __divq.S __divlu.S __divl.S
+SRCS+= __remqu.S __remq.S __remlu.S __reml.S
+CLEANFILES+=   __divqu.S __divq.S __divlu.S __divl.S
+CLEANFILES+=   __remqu.S __remq.S __remlu.S __reml.S
+
+__divqu.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__divqu')define(OP,\`div')define(S,\`false')"; \
+        echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__divq.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__divq')define(OP,\`div')define(S,\`true')"; \
+        echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__divlu.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__divlu')define(OP,\`div')define(S,\`false')"; \
+        echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__divl.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__divl')define(OP,\`div')define(S,\`true')"; \
+        echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__remqu.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__remqu')define(OP,\`rem')define(S,\`false')"; \
+        echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__remq.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__remq')define(OP,\`rem')define(S,\`true')"; \
+        echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__remlu.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__remlu')define(OP,\`rem')define(S,\`false')"; \
+        echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+__reml.S: ${M}/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`__reml')define(OP,\`rem')define(S,\`true')"; \
+        echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
diff --git a/sys/lib/libkern/arch/alpha/divrem.m4 b/sys/lib/libkern/arch/alpha/divrem.m4
new file mode 100644 (file)
index 0000000..348bbfa
--- /dev/null
@@ -0,0 +1,197 @@
+/*     $NetBSD: divrem.m4,v 1.8 2005/12/11 12:24:42 christos Exp $     */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Division and remainder.
+ *
+ * The use of m4 is modeled after the sparc code, but the algorithm is
+ * simple binary long division.
+ *
+ * Note that the loops could probably benefit from unrolling.
+ */
+
+/*
+ * M4 Parameters
+ * NAME                name of function to generate
+ * OP          OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12
+ * S           S=true: signed; S=false: unsigned
+ * WORDSIZE    total number of bits
+ */
+
+define(A, `t10')
+define(B, `t11')
+define(RESULT, `t12')
+
+define(BIT, `t0')
+define(I, `t1')
+define(CC, `t2')
+define(T_0, `t3')
+ifelse(S, `true', `define(NEG, `t4')')
+
+#include <machine/asm.h>
+
+LEAF(NAME, 0)                                  /* XXX */
+       lda     sp, -64(sp)
+       stq     BIT, 0(sp)
+       stq     I, 8(sp)
+       stq     CC, 16(sp)
+       stq     T_0, 24(sp)
+ifelse(S, `true',
+`      stq     NEG, 32(sp)')
+       stq     A, 40(sp)
+       stq     B, 48(sp)
+       mov     zero, RESULT                    /* Initialize result to zero */
+
+ifelse(S, `true',
+`
+       /* Compute sign of result.  If either is negative, this is easy.  */
+       or      A, B, NEG                       /* not the sign, but... */
+       srl     NEG, WORDSIZE - 1, NEG          /* rather, or of high bits */
+       blbc    NEG, Ldoit                      /* neither negative? do it! */
+
+ifelse(OP, `div',
+`      xor     A, B, NEG                       /* THIS is the sign! */
+', `   mov     A, NEG                          /* sign follows A. */
+')
+       srl     NEG, WORDSIZE - 1, NEG          /* make negation the low bit. */
+
+       srl     A, WORDSIZE - 1, I              /* is A negative? */
+       blbc    I, LnegB                        /* no. */
+       /* A is negative; flip it. */
+ifelse(WORDSIZE, `32', `
+       /* top 32 bits may be random junk */
+       zap     A, 0xf0, A
+')
+       subq    zero, A, A
+       srl     B, WORDSIZE - 1, I              /* is B negative? */
+       blbc    I, Ldoit                        /* no. */
+LnegB:
+       /* B is definitely negative, no matter how we got here. */
+ifelse(WORDSIZE, `32', `
+       /* top 32 bits may be random junk */
+       zap     B, 0xf0, B
+')
+       subq    zero, B, B
+Ldoit:
+')
+ifelse(WORDSIZE, `32', `
+       /*
+        * Clear the top 32 bits of each operand, as they may
+        * sign extension (if negated above), or random junk.
+        */
+       zap     A, 0xf0, A
+       zap     B, 0xf0, B
+')
+
+       /* kill the special cases. */
+       beq     B, Ldotrap                      /* division by zero! */
+
+       cmpult  A, B, CC                        /* A < B? */
+       /* RESULT is already zero, from above.  A is untouched. */
+       bne     CC, Lret_result
+
+       cmpeq   A, B, CC                        /* A == B? */
+       cmovne  CC, 1, RESULT
+       cmovne  CC, zero, A
+       bne     CC, Lret_result
+
+       /*
+        * Find out how many bits of zeros are at the beginning of the divisor.
+        */
+LBbits:
+       ldiq    T_0, 1                          /* I = 0; BIT = 1<<WORDSIZE-1 */
+       mov     zero, I
+       sll     T_0, WORDSIZE-1, BIT
+LBloop:
+       and     B, BIT, CC                      /* if bit in B is set, done. */
+       bne     CC, LAbits
+       addq    I, 1, I                         /* increment I, shift bit */
+       srl     BIT, 1, BIT
+       cmplt   I, WORDSIZE-1, CC               /* if I leaves one bit, done. */
+       bne     CC, LBloop
+
+LAbits:
+       beq     I, Ldodiv                       /* If I = 0, divide now.  */
+       ldiq    T_0, 1                          /* BIT = 1<<WORDSIZE-1 */
+       sll     T_0, WORDSIZE-1, BIT
+
+LAloop:
+       and     A, BIT, CC                      /* if bit in A is set, done. */
+       bne     CC, Ldodiv
+       subq    I, 1, I                         /* decrement I, shift bit */
+       srl     BIT, 1, BIT
+       bne     I, LAloop                       /* If I != 0, loop again */
+
+Ldodiv:
+       sll     B, I, B                         /* B <<= i */
+       ldiq    T_0, 1
+       sll     T_0, I, BIT
+
+Ldivloop:
+       cmpult  A, B, CC
+       or      RESULT, BIT, T_0
+       cmoveq  CC, T_0, RESULT
+       subq    A, B, T_0
+       cmoveq  CC, T_0, A
+       srl     BIT, 1, BIT
+       srl     B, 1, B
+       beq     A, Lret_result
+       bne     BIT, Ldivloop
+
+Lret_result:
+ifelse(OP, `div',
+`', `  mov     A, RESULT
+')
+ifelse(S, `true',
+`
+       /* Check to see if we should negate it. */
+       subq    zero, RESULT, T_0
+       cmovlbs NEG, T_0, RESULT
+')
+
+       ldq     BIT, 0(sp)
+       ldq     I, 8(sp)
+       ldq     CC, 16(sp)
+       ldq     T_0, 24(sp)
+ifelse(S, `true',
+`      ldq     NEG, 32(sp)')
+       ldq     A, 40(sp)
+       ldq     B, 48(sp)
+       lda     sp, 64(sp)
+       ret     zero, (t9), 1
+
+Ldotrap:
+       ldiq    a0, -2                  /* This is the signal to SIGFPE! */
+       call_pal PAL_gentrap
+ifelse(OP, `div',
+`', `  mov     zero, A                 /* so that zero will be returned */
+')
+       br      zero, Lret_result
+
+END(NAME)
diff --git a/sys/lib/libkern/arch/alpha/htonl.S b/sys/lib/libkern/arch/alpha/htonl.S
new file mode 100644 (file)
index 0000000..e1871e0
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: htonl.S,v 1.1 1996/04/17 22:46:41 cgd Exp $    */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    htonl
+
+#include "byte_swap_4.S"
diff --git a/sys/lib/libkern/arch/alpha/htons.S b/sys/lib/libkern/arch/alpha/htons.S
new file mode 100644 (file)
index 0000000..7ab417a
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: htons.S,v 1.1 1996/04/17 22:46:43 cgd Exp $    */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    htons
+
+#include "byte_swap_2.S"
diff --git a/sys/lib/libkern/arch/alpha/ntohl.S b/sys/lib/libkern/arch/alpha/ntohl.S
new file mode 100644 (file)
index 0000000..9689ef1
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: ntohl.S,v 1.1 1996/04/17 22:46:45 cgd Exp $    */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    ntohl
+
+#include "byte_swap_4.S"
diff --git a/sys/lib/libkern/arch/alpha/ntohs.S b/sys/lib/libkern/arch/alpha/ntohs.S
new file mode 100644 (file)
index 0000000..1336213
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: ntohs.S,v 1.1 1996/04/17 22:46:46 cgd Exp $    */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    ntohs
+
+#include "byte_swap_2.S"
diff --git a/sys/lib/libkern/arch/arm/Makefile.inc b/sys/lib/libkern/arch/arm/Makefile.inc
new file mode 100644 (file)
index 0000000..678e93d
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile.inc,v 1.9 2009/08/14 19:23:53 dsl Exp $
+
+SRCS+= byte_swap_2.S byte_swap_4.S
+SRCS+= ffs.S
+SRCS+= divsi3.S clzsi2.S
+SRCS+= memcmp.S memcpy.S memset.S memmove.S strcmp.S strncmp.S
diff --git a/sys/lib/libkern/arch/arm/clzsi2.S b/sys/lib/libkern/arch/arm/clzsi2.S
new file mode 100644 (file)
index 0000000..6bf3ff9
--- /dev/null
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <machine/asm.h>
+
+       .text
+ENTRY(__clzdi2)
+       movs    r3, r0
+       movne   r0, #31
+       bne     .L_clz
+       movs    r3, r1
+       movne   r0, #63
+       bne     .L_clz
+       mov     r0, #64
+       RET
+END(__clzdi2)
+
+ENTRY(__clzsi2)
+       movs    r3, r0
+       moveq   r0, #32
+       RETc(eq)
+       mov     r0, #31
+.L_clz:
+       mvn     r1, #0
+#ifndef __OPTIMIZE_SIZE__
+       eor     r1, r1, r1, lsr #16     /* 0xFFFFFFFF -> 0xFFFF0000 */
+       ands    r2, r3, r1      
+       eorne   r0, r0, #16
+       movne   r3, r2
+       eor     r1, r1, r1, lsr #8      /* 0xFFFF0000 -> 0xFF00FF00 */
+       ands    r2, r3, r1      
+       eorne   r0, r0, #8
+       movne   r3, r2
+       eor     r1, r1, r1, lsr #4      /* 0xFF00FF00 -> 0xF0F0F0F0 */
+       ands    r2, r3, r1      
+       eorne   r0, r0, #4
+       movne   r3, r2
+       eor     r1, r1, r1, lsr #2      /* 0xF0F0F0F0 -> 0xCCCCCCCC */
+       ands    r2, r3, r1      
+       eorne   r0, r0, #2
+       movne   r3, r2
+       eor     r1, r1, r1, lsr #1      /* 0xCCCCCCCC -> 0xAAAAAAAA */
+       ands    r2, r3, r1      
+       eorne   r0, r0, #1
+#if 0
+       teqeq   r3, #0
+       addeq   r0, r0, #1
+#endif
+#else
+       mov     r2, #16
+1:     eor     r1, r1, r1, lsr r2
+       ands    ip, r3, r1      
+       movne   r3, ip
+       eorne   r0, r0, r2
+       movs    r2, r2, lsr #1
+       bne     1b
+#if 0
+       teq     r3, #0
+       addeq   r0, r0, #1
+#endif
+#endif /* __OPTIMIZE_SIZE__ */
+       RET
+END(__clzsi2)
diff --git a/sys/lib/libkern/arch/hppa/Makefile.inc b/sys/lib/libkern/arch/hppa/Makefile.inc
new file mode 100644 (file)
index 0000000..570b29f
--- /dev/null
@@ -0,0 +1,12 @@
+#      $NetBSD: Makefile.inc,v 1.11 2009/09/22 09:57:16 pooka Exp $
+
+SRCS+= milli.S
+SRCS+= bcopy.S memcpy.S memmove.S
+
+# XXX: spcopy does not really belong in libkern in the first place
+.ifndef RUMPKERNEL
+SRCS+= spcopy.S
+.endif
+
+SRCS+= ashrdi3.c divdi3.c    
+SRCS+= ffs.c bswap16.c bswap32.c
diff --git a/sys/lib/libkern/arch/hppa/bcopy.S b/sys/lib/libkern/arch/hppa/bcopy.S
new file mode 100644 (file)
index 0000000..98dc80c
--- /dev/null
@@ -0,0 +1,618 @@
+/*     $NetBSD: bcopy.S,v 1.14 2011/01/31 12:10:58 skrll Exp $ */
+
+/*
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthew Fredette.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copy routines for NetBSD/hppa.
+ */
+
+#undef _LOCORE
+#define _LOCORE        /* XXX fredette - unfortunate */
+
+#if defined(SPCOPY) && !defined(_STANDALONE)
+
+#include "opt_multiprocessor.h"
+
+#include <machine/cpu.h>
+
+#endif
+
+#include <machine/asm.h>
+#include <machine/frame.h>
+#include <machine/reg.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+RCSID("$NetBSD: bcopy.S,v 1.14 2011/01/31 12:10:58 skrll Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * The stbys instruction is a little asymmetric.  When (%r2 & 3)
+ * is zero, stbys,b,m %r1, 4(%r2) works like stws,ma.  You
+ * might then wish that when (%r2 & 3) == 0, stbys,e,m %r1, -4(%r2)
+ * worked like stws,mb.  But it doesn't.
+ *
+ * This macro works around this problem.  It requires that %t2
+ * hold the number of bytes that will be written by this store
+ * (meaning that it ranges from one to four).
+ *
+ * Watch the delay-slot trickery here.  The comib is used to set
+ * up which instruction, either the stws or the stbys, is run
+ * in the delay slot of the b instruction.
+ */
+#define _STBYS_E_M(r, dst_spc, dst_off)                                  \
+       comib,<>        4, %t2, 4                               ! \
+       b               4                                       ! \
+       stws,mb         r, -4(dst_spc, dst_off)                 ! \
+       stbys,e,m       r, 0(dst_spc, dst_off)
+
+/*
+ * This macro does a bulk copy with no shifting.  cmplt and m are
+ * the completer and displacement multiplier, respectively, for
+ * the load and store instructions.
+ */
+#define _COPY(src_spc, src_off, dst_spc, dst_off, count, cmplt, m) \
+                                                               ! \
+       /*                                                      ! \
+        * Loop storing 16 bytes at a time.  Since count        ! \
+        * may be > INT_MAX, we have to be careful and          ! \
+        * avoid comparisons that treat it as a signed          ! \
+        * quantity, until after this loop, when count          ! \
+        * is guaranteed to be less than 16.                    ! \
+        */                                                     ! \
+       comib,>>=,n     15, count, _LABEL(_skip16)              ! \
+.label _LABEL(_loop16)                                         ! \
+       addi            -16, count, count                       ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t1              ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t2              ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t3              ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t4              ! \
+       stws,cmplt      %t1, m*4(dst_spc, dst_off)              ! \
+       stws,cmplt      %t2, m*4(dst_spc, dst_off)              ! \
+       stws,cmplt      %t3, m*4(dst_spc, dst_off)              ! \
+       comib,<<        15, count, _LABEL(_loop16)              ! \
+       stws,cmplt      %t4, m*4(dst_spc, dst_off)              ! \
+.label _LABEL(_skip16)                                         ! \
+                                                               ! \
+       /* Loop storing 4 bytes at a time. */                   ! \
+       addib,<,n       -4, count, _LABEL(_skip4)               ! \
+.label _LABEL(_loop4)                                          ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t1              ! \
+       addib,>=        -4, count, _LABEL(_loop4)               ! \
+       stws,cmplt      %t1, m*4(dst_spc, dst_off)              ! \
+.label _LABEL(_skip4)                                          ! \
+       /* Restore the correct count. */                        ! \
+       addi            4, count, count                         ! \
+                                                               ! \
+.label _LABEL(_do1)                                            ! \
+                                                               ! \
+       /* Loop storing 1 byte at a time. */                    ! \
+       addib,<,n       -1, count, _LABEL(_skip1)               ! \
+.label _LABEL(_loop1)                                          ! \
+       ldbs,cmplt      m*1(src_spc, src_off), %t1              ! \
+       addib,>=        -1, count, _LABEL(_loop1)               ! \
+       stbs,cmplt      %t1, m*1(dst_spc, dst_off)              ! \
+.label _LABEL(_skip1)                                          ! \
+       /* Restore the correct count. */                        ! \
+       b               _LABEL(_done)                           ! \
+       addi            1, count, count
+
+/*
+ * This macro is definitely strange.  It exists purely to
+ * allow the _COPYS macro to be reused, but because it
+ * requires this long attempt to explain it, I'm starting
+ * to doubt the value of that.
+ *
+ * Part of the expansion of the _COPYS macro below are loops
+ * that copy four words or one word at a time, performing shifts
+ * to get data to line up correctly in the destination buffer.
+ *
+ * The _COPYS macro is used when copying backwards, as well
+ * as forwards.  The 4-word loop always loads into %t1, %t2, %t3,
+ * and %t4 in that order.  This means that when copying forward,
+ * %t1 will have the word from the lowest address, and %t4 will
+ * have the word from the highest address.  When copying
+ * backwards, the opposite is true.
+ *
+ * The shift instructions need pairs of registers with adjacent
+ * words, with the register containing the word from the lowest
+ * address *always* coming first.  It is this assymetry that
+ * gives rise to this macro - depending on which direction
+ * we're copying in, these ordered pairs are different.
+ *
+ * Fortunately, we can compute those register numbers at compile
+ * time, and assemble them manually into a shift instruction.
+ * That's what this macro does.
+ *
+ * This macro takes two arguments.  n ranges from 0 to 3 and
+ * is the "shift number", i.e., n = 0 means we're doing the
+ * shift for what will be the first store.
+ *
+ * m is the displacement multiplier from the _COPYS macro call.
+ * This is 1 for a forward copy and -1 for a backwards copy.
+ * So, the ((m + 1) / 2) term yields 0 for a backwards copy and
+ * 1 for a forward copy, and the ((m - 1) / 2) term yields
+ * 0 for a forward copy, and -1 for a backwards copy.
+ * These terms are used to discriminate the register computations
+ * below.
+ *
+ * When copying forward, then, the first register used with
+ * the first vshd will be 19 + (3 - ((0 - 1) & 3)), or %t4,
+ * which matches _COPYS' requirement that the word last loaded
+ * be in %t4.  The first register used for the second vshd
+ * will then "wrap" around to 19 + (3 - ((1 - 1) & 3)), or %t1.
+ * And so on to %t2 and %t3.
+ *
+ * When copying forward, the second register used with the first
+ * vshd will be (19 + (3 - ((n + 0) & 3)), or %t1.  It will
+ * continue to be %t2, then %t3, and finally %t4.
+ *
+ * When copying backwards, the values for the first and second
+ * register for each vshd are reversed from the forwards case.
+ * (Symmetry reclaimed!)  Proving this is "left as an exercise
+ * for the reader" (remember the different discriminating values!)
+ */
+#define _VSHD(n, m, t)                                           \
+       .word (0xd0000000                                       | \
+       ((19 + (3 - ((n - 1 * ((m + 1) / 2)) & 3))) << 16)      | \
+       ((19 + (3 - ((n + 1 * ((m - 1) / 2)) & 3))) << 21)      | \
+       (t))
+
+/*
+ * This macro does a bulk copy with shifting.  cmplt and m are
+ * the completer and displacement multiplier, respectively, for
+ * the load and store instructions.  It is assumed that the
+ * word last loaded is already in %t4.
+ */
+#define _COPYS(src_spc, src_off, dst_spc, dst_off, count, cmplt, m) \
+                                                               ! \
+       /*                                                      ! \
+        * Loop storing 16 bytes at a time.  Since count        ! \
+        * may be > INT_MAX, we have to be careful and          ! \
+        * avoid comparisons that treat it as a signed          ! \
+        * quantity, until after this loop, when count          ! \
+        * is guaranteed to be less than 16.                    ! \
+        */                                                     ! \
+       comib,>>=,n     15, count, _LABEL(S_skip16)             ! \
+.label _LABEL(S_loop16)                                                ! \
+       addi            -16, count, count                       ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t1              ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t2              ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t3              ! \
+       _VSHD(0, m, 1)  /* vshd %t4, %t1, %r1 */                ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t4              ! \
+       _VSHD(1, m, 22) /* vshd %t1, %t2, %t1 */                ! \
+       _VSHD(2, m, 21) /* vshd %t2, %t3, %t2 */                ! \
+       _VSHD(3, m, 20) /* vshd %t3, %t4, %t3 */                ! \
+       stws,cmplt      %r1, m*4(dst_spc, dst_off)              ! \
+       stws,cmplt      %t1, m*4(dst_spc, dst_off)              ! \
+       stws,cmplt      %t2, m*4(dst_spc, dst_off)              ! \
+       comib,<<        15, count, _LABEL(S_loop16)             ! \
+       stws,cmplt      %t3, m*4(dst_spc, dst_off)              ! \
+.label _LABEL(S_skip16)                                                ! \
+                                                               ! \
+       /* Loop storing 4 bytes at a time. */                   ! \
+       addib,<,n       -4, count, _LABEL(S_skip4)              ! \
+.label _LABEL(S_loop4)                                         ! \
+       ldws,cmplt      m*4(src_spc, src_off), %t1              ! \
+       _VSHD(0, m, 1)  /* into %r1 (1) */                      ! \
+       copy            %t1, %t4                                ! \
+       addib,>=        -4, count, _LABEL(S_loop4)              ! \
+       stws,cmplt      %r1, m*4(dst_spc, dst_off)              ! \
+.label _LABEL(S_skip4)                                         ! \
+                                                               ! \
+       /*                                                      ! \
+        * We now need to "back up" src_off by the              ! \
+        * number of bytes remaining in the FIFO                ! \
+        * (i.e., the number of bytes remaining in %t4),        ! \
+        * because (the correct) count still includes           ! \
+        * these bytes, and we intent to keep it that           ! \
+        * way, and finish with the single-byte copier.         ! \
+        *                                                      ! \
+        * The number of bytes remaining in the FIFO is         ! \
+        * related to the shift count, so recover it,           ! \
+        * restoring the correct count at the same time.        ! \
+        */                                                     ! \
+       mfctl   %cr11, %t1                                      ! \
+       addi    4, count, count                                 ! \
+       shd     %r0, %t1, 3, %t1                                ! \
+                                                               ! \
+       /*                                                      ! \
+        * If we're copying forward, the shift count            ! \
+        * is the number of bytes remaining in the              ! \
+        * FIFO, and we want to subtract it from src_off.       ! \
+        * If we're copying backwards, (4 - shift count)        ! \
+        * is the number of bytes remaining in the FIFO,        ! \
+        * and we want to add it to src_off.                    ! \
+        *                                                      ! \
+        * We observe that x + (4 - y) = x - (y - 4),           ! \
+        * and introduce this instruction to add -4 when        ! \
+        * m is -1, although this does mean one extra           ! \
+        * instruction in the forward case.                     ! \
+        */                                                     ! \
+       addi    4*((m - 1) / 2), %t1, %t1                       ! \
+                                                               ! \
+       /* Now branch to the byte-at-a-time loop. */            ! \
+       b       _LABEL(_do1)                                    ! \
+       sub     src_off, %t1, src_off
+
+/*
+ * This macro copies a region in the forward direction.
+ */
+#define _COPY_FORWARD(src_spc, src_off, dst_spc, dst_off, count)  \
+                                                               ! \
+       /*                                                      ! \
+        * Since in the shifting-left case we will              ! \
+        * load 8 bytes before checking count, to               ! \
+        * keep things simple, branch to the byte               ! \
+        * copier unless we're copying at least 8.              ! \
+        */                                                     ! \
+       comib,>>,n      8, count, _LABEL(_do1)                  ! \
+                                                               ! \
+       /*                                                      ! \
+        * Once we 4-byte align the source offset,              ! \
+        * figure out how many bytes from the region            ! \
+        * will be in the first 4-byte word we read.            ! \
+        * Ditto for writing the destination offset.            ! \
+        */                                                     ! \
+       extru           src_off, 31, 2, %t1                     ! \
+       extru           dst_off, 31, 2, %t2                     ! \
+       subi            4, %t1, %t1                             ! \
+       subi            4, %t2, %t2                             ! \
+                                                               ! \
+       /*                                                      ! \
+        * Calculate the byte shift required.  A                ! \
+        * positive value means a source 4-byte word            ! \
+        * has to be shifted to the right to line up            ! \
+        * as a destination 4-byte word.                        ! \
+        */                                                     ! \
+       sub             %t1, %t2, %t1                           ! \
+                                                               ! \
+       /* 4-byte align src_off. */                             ! \
+       depi            0, 31, 2, src_off                       ! \
+                                                               ! \
+       /*                                                      ! \
+        * It's somewhat important to note that this            ! \
+        * code thinks of count as "the number of bytes         ! \
+        * that haven't been stored yet", as opposed to         ! \
+        * "the number of bytes that haven't been copied        ! \
+        * yet".  The distinction is subtle, but becomes        ! \
+        * apparent at the end of the shifting code, where      ! \
+        * we "back up" src_off to correspond to count,         ! \
+        * as opposed to flushing the FIFO.                     ! \
+        *                                                      ! \
+        * We calculated above how many bytes our first         ! \
+        * store will store, so update count now.               ! \
+        *                                                      ! \
+        * If the shift is zero, strictly as an optimization    ! \
+        * we use a copy loop that does no shifting.            ! \
+        */                                                     ! \
+       comb,<>         %r0, %t1, _LABEL(_shifting)             ! \
+       sub             count, %t2, count                       ! \
+                                                               ! \
+       /* Load and store the first word. */                    ! \
+       ldws,ma         4(src_spc, src_off), %t4                ! \
+       stbys,b,m       %t4, 4(dst_spc, dst_off)                ! \
+                                                               ! \
+       /* Do the rest of the copy. */                          ! \
+       _COPY(src_spc,src_off,dst_spc,dst_off,count,ma,1)       ! \
+                                                               ! \
+.label _LABEL(_shifting)                                       ! \
+                                                               ! \
+       /*                                                      ! \
+        * If shift < 0, we need to shift words to the          ! \
+        * left.  Since we can't do this directly, we           ! \
+        * adjust the shift so it's a shift to the right        ! \
+        * and load the first word into the high word of        ! \
+        * the FIFO.  Otherwise, we load a zero into the        ! \
+        * high word of the FIFO.                               ! \
+        */                                                     ! \
+       comb,<=         %r0, %t1, _LABEL(_shiftingrt)           ! \
+       copy            %r0, %t3                                ! \
+       addi            4, %t1, %t1                             ! \
+       ldws,ma         4(src_spc, src_off), %t3                ! \
+.label _LABEL(_shiftingrt)                                     ! \
+                                                               ! \
+       /*                                                      ! \
+        * Turn the shift byte count into a bit count,          ! \
+        * load the next word, set the Shift Amount             ! \
+        * Register, and form and store the first word.         ! \
+        */                                                     ! \
+       sh3add          %t1, %r0, %t1                           ! \
+       ldws,ma         4(src_spc, src_off), %t4                ! \
+       mtctl           %t1, %cr11                              ! \
+       vshd            %t3, %t4, %r1                           ! \
+       stbys,b,m       %r1, 4(dst_spc, dst_off)                ! \
+                                                               ! \
+       /* Do the rest of the copy. */                          ! \
+       _COPYS(src_spc,src_off,dst_spc,dst_off,count,ma,1)
+
+/* This macro copies a region in the reverse direction. */
+#define _COPY_REVERSE(src_spc, src_off, dst_spc, dst_off, count)  \
+                                                               ! \
+       /* Immediately add count to both offsets. */            ! \
+       add     src_off, count, src_off                         ! \
+       add     dst_off, count, dst_off                         ! \
+                                                               ! \
+       /*                                                      ! \
+        * Since in the shifting-right case we                  ! \
+        * will load 8 bytes before checking                    ! \
+        * count, to keep things simple, branch                 ! \
+        * to the byte copier unless we're                      ! \
+        * copying at least 8 bytes.                            ! \
+        */                                                     ! \
+       comib,>>,n      8, count, _LABEL(_do1)                  ! \
+                                                               ! \
+       /*                                                      ! \
+        * Once we 4-byte align the source offset,              ! \
+        * figure out how many bytes from the region            ! \
+        * will be in the first 4-byte word we read.            ! \
+        * Ditto for writing the destination offset.            ! \
+        */                                                     ! \
+       extru,<>        src_off, 31, 2, %t1                     ! \
+       ldi             4, %t1                                  ! \
+       extru,<>        dst_off, 31, 2, %t2                     ! \
+       ldi             4, %t2                                  ! \
+                                                               ! \
+       /*                                                      ! \
+        * Calculate the byte shift required.  A                ! \
+        * positive value means a source 4-byte                 ! \
+        * word has to be shifted to the right to               ! \
+        * line up as a destination 4-byte word.                ! \
+        */                                                     ! \
+       sub             %t2, %t1, %t1                           ! \
+                                                               ! \
+       /*                                                      ! \
+        * 4-byte align src_off, leaving it pointing            ! \
+        * to the 4-byte word *after* the next word             ! \
+        * we intend to load.                                   ! \
+        *                                                      ! \
+        * It's somewhat important to note that this            ! \
+        * code thinks of count as "the number of bytes         ! \
+        * that haven't been stored yet", as opposed to         ! \
+        * "the number of bytes that haven't been copied        ! \
+        * yet".  The distinction is subtle, but becomes        ! \
+        * apparent at the end of the shifting code, where      ! \
+        * we "back up" src_off to correspond to count,         ! \
+        * as opposed to flushing the FIFO.                     ! \
+        *                                                      ! \
+        * We calculated above how many bytes our first         ! \
+        * store will store, so update count now.               ! \
+        *                                                      ! \
+        * If the shift is zero, we use a copy loop that        ! \
+        * does no shifting.  NB: unlike the forward case,      ! \
+        * this is NOT strictly an optimization.  If the        ! \
+        * SAR is zero the vshds do NOT do the right thing.     ! \
+        * This is another assymetry more or less the "fault"   ! \
+        * of vshd.                                             ! \
+        */                                                     ! \
+       addi            3, src_off, src_off                     ! \
+       sub             count, %t2, count                       ! \
+       comb,<>         %r0, %t1, _LABEL(_shifting)             ! \
+       depi            0, 31, 2, src_off                       ! \
+                                                               ! \
+       /* Load and store the first word. */                    ! \
+       ldws,mb         -4(src_spc, src_off), %t4               ! \
+       _STBYS_E_M(%t4, dst_spc, dst_off)                       ! \
+                                                               ! \
+       /* Do the rest of the copy. */                          ! \
+       _COPY(src_spc,src_off,dst_spc,dst_off,count,mb,-1)      ! \
+                                                               ! \
+.label _LABEL(_shifting)                                       ! \
+                                                               ! \
+       /*                                                      ! \
+        * If shift < 0, we need to shift words to the          ! \
+        * left.  Since we can't do this directly, we           ! \
+        * adjust the shift so it's a shift to the right        ! \
+        * and load a zero in to the low word of the FIFO.      ! \
+        * Otherwise, we load the first word into the           ! \
+        * low word of the FIFO.                                ! \
+        *                                                      ! \
+        * Note the nullification trickery here.  We            ! \
+        * assume that we're shifting to the left, and          ! \
+        * load zero into the low word of the FIFO.  Then       ! \
+        * we nullify the addi if we're shifting to the         ! \
+        * right.  If the addi is not nullified, we are         ! \
+        * shifting to the left, so we nullify the load.        ! \
+        * we branch if we're shifting to the                   ! \
+        */                                                     ! \
+       copy            %r0, %t3                                ! \
+       comb,<=,n       %r0, %t1, 0                             ! \
+       addi,tr         4, %t1, %t1                             ! \
+       ldws,mb         -4(src_spc, src_off), %t3               ! \
+                                                               ! \
+       /*                                                      ! \
+        * Turn the shift byte count into a bit count,          ! \
+        * load the next word, set the Shift Amount             ! \
+        * Register, and form and store the first word.         ! \
+        */                                                     ! \
+       sh3add          %t1, %r0, %t1                           ! \
+       ldws,mb         -4(src_spc, src_off), %t4               ! \
+       mtctl           %t1, %cr11                              ! \
+       vshd            %t4, %t3, %r1                           ! \
+       _STBYS_E_M(%r1, dst_spc, dst_off)                       ! \
+                                                               ! \
+       /* Do the rest of the copy. */                          ! \
+       _COPYS(src_spc,src_off,dst_spc,dst_off,count,mb,-1)
+
+/*
+ * For paranoia, when things aren't going well, enable this
+ * code to assemble byte-at-a-time-only copying.
+ */
+#if 1
+#undef _COPY_FORWARD
+#define _COPY_FORWARD(src_spc, src_off, dst_spc, dst_off, count)  \
+       comb,=,n        %r0, count, _LABEL(_done)               ! \
+       ldbs,ma         1(src_spc, src_off), %r1                ! \
+       addib,<>        -1, count, -12                          ! \
+       stbs,ma         %r1, 1(dst_spc, dst_off)                ! \
+       b,n             _LABEL(_done)
+#undef _COPY_REVERSE
+#define _COPY_REVERSE(src_spc, src_off, dst_spc, dst_off, count)  \
+       comb,=          %r0, count, _LABEL(_done)               ! \
+       add             src_off, count, src_off                 ! \
+       add             dst_off, count, dst_off                 ! \
+       ldbs,mb         -1(src_spc, src_off), %r1               ! \
+       addib,<>        -1, count, -12                          ! \
+       stbs,mb         %r1, -1(dst_spc, dst_off)               ! \
+       b,n             _LABEL(_done)
+#endif
+
+/*
+ * If none of the following are defined, define BCOPY.
+ */
+#if !(defined(SPCOPY) || defined(MEMCPY) || defined(MEMMOVE))
+#define BCOPY
+#endif
+
+#if defined(SPCOPY) && !defined(_STANDALONE)
+
+#include <sys/errno.h>
+#include "assym.h"
+
+/*
+ * int spcopy(pa_space_t ssp, const void *src, pa_space_t dsp, void *dst,
+ *     size_t len)
+ *
+ * We assume that the regions do not overlap.
+ */
+LEAF_ENTRY(spcopy)
+
+        /*
+        * Setup the fault handler, which will fill in %ret0 if triggered.
+        */
+       GET_CURLWP(%r31)
+#ifdef DIAGNOSTIC
+       comb,<>,n %r0, %r31, Lspcopy_curlwp_ok
+       ldil    L%panic, %r1
+       ldil    L%Lspcopy_curlwp_bad, %arg0
+       ldo     R%panic(%r1), %r1
+       ldo     R%Lspcopy_curlwp_bad(%arg0), %arg0
+       .call
+       bv,n    %r0(%r1)
+       nop
+Lspcopy_curlwp_bad:
+       .asciz  "spcopy: curlwp == NULL\n"
+       .align  8
+Lspcopy_curlwp_ok:
+#endif /* DIAGNOSTIC */
+       ldil    L%spcopy_fault, %r1
+       ldw     L_PCB(%r31), %r31
+       ldo     R%spcopy_fault(%r1), %r1
+       stw     %r1, PCB_ONFAULT(%r31)
+
+       /* Setup the space registers. */
+       mfsp    %sr2, %ret1
+       mtsp    %arg0, %sr1
+       mtsp    %arg2, %sr2
+
+       /* Get the len argument and do the copy. */
+       ldw     HPPA_FRAME_ARG(4)(%sp), %arg0
+#define        _LABEL(l) __CONCAT(spcopy,l)
+       _COPY_FORWARD(%sr1,%arg1,%sr2,%arg3,%arg0)
+_LABEL(_done):
+
+       /* Return. */
+       copy    %r0, %ret0
+ALTENTRY(spcopy_fault)
+       stw     %r0, PCB_ONFAULT(%r31)
+       bv      %r0(%rp)
+       mtsp    %ret1, %sr2
+EXIT(spcopy)
+#endif /* SPCOPY && !_STANDALONE */
+
+#ifdef MEMCPY
+/*
+ * void *memcpy(void *restrict dst, const void *restrict src, size_t len);
+ *
+ * memcpy is specifically restricted to working on
+ * non-overlapping regions, so we can just copy forward.
+ */
+LEAF_ENTRY(memcpy)
+       copy    %arg0, %ret0
+#define        _LABEL(l) __CONCAT(memcpy,l)
+       _COPY_FORWARD(%sr0,%arg1,%sr0,%arg0,%arg2)
+_LABEL(_done):
+       bv,n    %r0(%rp)
+       nop
+EXIT(memcpy)
+#endif /* MEMCPY */
+
+#ifdef BCOPY
+/*
+ * void bcopy(const void *src, void *dst, size_t len);
+ */
+LEAF_ENTRY(bcopy)
+       copy    %arg0, %r1
+       copy    %arg1, %arg0
+       copy    %r1, %arg1
+       /* FALLTHROUGH */
+#define _LABEL_F(l) __CONCAT(bcopy_F,l)
+#define _LABEL_R(l) __CONCAT(bcopy_R,l)
+#endif
+
+#ifdef MEMMOVE
+/*
+ * void *memmove(void *dst, const void *src, size_t len);
+ */
+LEAF_ENTRY(memmove)
+#define _LABEL_F(l) __CONCAT(memmove_F,l)
+#define _LABEL_R(l) __CONCAT(memmove_R,l)
+       copy    %arg0, %ret0
+#endif /* MEMMOVE */
+
+#if defined(BCOPY) || defined(MEMMOVE)
+
+       /*
+        * If src >= dst or src + len <= dst, we copy
+        * forward, else we copy in reverse.
+        */
+       add             %arg1, %arg2, %r1
+       comb,>>=,n      %arg1, %arg0, 0
+       comb,>>,n       %r1, %arg0, _LABEL_R(_go)
+
+#define _LABEL _LABEL_F
+       _COPY_FORWARD(%sr0,%arg1,%sr0,%arg0,%arg2)
+#undef _LABEL
+
+_LABEL_R(_go):
+#define _LABEL _LABEL_R
+       _COPY_REVERSE(%sr0,%arg1,%sr0,%arg0,%arg2)
+#undef _LABEL
+
+_LABEL_F(_done):
+_LABEL_R(_done):
+       bv,n    %r0(%rp)
+       nop
+#ifdef BCOPY
+EXIT(bcopy)
+#else
+EXIT(memmove)
+#endif
+#endif /* BCOPY || MEMMOVE */
diff --git a/sys/lib/libkern/arch/hppa/memcpy.S b/sys/lib/libkern/arch/hppa/memcpy.S
new file mode 100644 (file)
index 0000000..edb2204
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: memcpy.S,v 1.1 2002/06/06 20:03:38 fredette Exp $      */
+
+#define MEMCPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/hppa/memmove.S b/sys/lib/libkern/arch/hppa/memmove.S
new file mode 100644 (file)
index 0000000..24a2872
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: memmove.S,v 1.1 2002/06/06 20:03:38 fredette Exp $     */
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/hppa/milli.S b/sys/lib/libkern/arch/hppa/milli.S
new file mode 100644 (file)
index 0000000..adc7ca1
--- /dev/null
@@ -0,0 +1,1814 @@
+;      $NetBSD: milli.S,v 1.1 2002/06/06 20:03:39 fredette Exp $
+;
+;      $OpenBSD: milli.S,v 1.5 2001/03/29 04:08:20 mickey Exp $
+;
+;  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
+;
+;  To anyone who acknowledges that this file is provided "AS IS"
+;  without any express or implied warranty:
+;      permission to use, copy, modify, and distribute this file
+;  for any purpose is hereby granted without fee, provided that
+;  the above copyright notice and this notice appears in all
+;  copies, and that the name of Hewlett-Packard Company not be
+;  used in advertising or publicity pertaining to distribution
+;  of the software without specific, written prior permission.
+;  Hewlett-Packard Company makes no representations about the
+;  suitability of this software for any purpose.
+;
+
+; Standard Hardware Register Definitions for Use with Assembler
+; version A.08.06
+;      - fr16-31 added at Utah
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+; Hardware General Registers
+r0: .equ       0
+
+r1: .equ       1
+
+r2: .equ       2
+
+r3: .equ       3
+
+r4: .equ       4
+
+r5: .equ       5
+
+r6: .equ       6
+
+r7: .equ       7
+
+r8: .equ       8
+
+r9: .equ       9
+
+r10: .equ      10
+
+r11: .equ      11
+
+r12: .equ      12
+
+r13: .equ      13
+
+r14: .equ      14
+
+r15: .equ      15
+
+r16: .equ      16
+
+r17: .equ      17
+
+r18: .equ      18
+
+r19: .equ      19
+
+r20: .equ      20
+
+r21: .equ      21
+
+r22: .equ      22
+
+r23: .equ      23
+
+r24: .equ      24
+
+r25: .equ      25
+
+r26: .equ      26
+
+r27: .equ      27
+
+r28: .equ      28
+
+r29: .equ      29
+
+r30: .equ      30
+
+r31: .equ      31
+
+; Hardware Space Registers
+sr0: .equ      0
+
+sr1: .equ      1
+
+sr2: .equ      2
+
+sr3: .equ      3
+
+sr4: .equ      4
+
+sr5: .equ      5
+
+sr6: .equ      6
+
+sr7: .equ      7
+
+; Hardware Floating Point Registers
+fr0: .equ      0
+
+fr1: .equ      1
+
+fr2: .equ      2
+
+fr3: .equ      3
+
+fr4: .equ      4
+
+fr5: .equ      5
+
+fr6: .equ      6
+
+fr7: .equ      7
+
+fr8: .equ      8
+
+fr9: .equ      9
+
+fr10: .equ     10
+
+fr11: .equ     11
+
+fr12: .equ     12
+
+fr13: .equ     13
+
+fr14: .equ     14
+
+fr15: .equ     15
+
+fr16: .equ     16
+
+fr17: .equ     17
+
+fr18: .equ     18
+
+fr19: .equ     19
+
+fr20: .equ     20
+
+fr21: .equ     21
+
+fr22: .equ     22
+
+fr23: .equ     23
+
+fr24: .equ     24
+
+fr25: .equ     25
+
+fr26: .equ     26
+
+fr27: .equ     27
+
+fr28: .equ     28
+
+fr29: .equ     29
+
+fr30: .equ     30
+
+fr31: .equ     31
+
+; Hardware Control Registers
+cr0: .equ      0
+
+rctr: .equ     0                       ; Recovery Counter Register
+
+cr8: .equ      8                       ; Protection ID 1
+
+pidr1: .equ    8
+
+cr9: .equ      9                       ; Protection ID 2
+
+pidr2: .equ    9
+
+cr10: .equ     10
+
+ccr: .equ      10                      ; Coprocessor Confiquration Register
+
+cr11: .equ     11
+
+sar: .equ      11                      ; Shift Amount Register
+
+cr12: .equ     12
+
+pidr3: .equ    12                      ; Protection ID 3
+
+cr13: .equ     13
+
+pidr4: .equ    13                      ; Protection ID 4
+
+cr14: .equ     14
+
+iva: .equ      14                      ; Interrupt Vector Address
+
+cr15: .equ     15
+
+eiem: .equ     15                      ; External Interrupt Enable Mask
+
+cr16: .equ     16
+
+itmr: .equ     16                      ; Interval Timer
+
+cr17: .equ     17
+
+pcsq: .equ     17                      ; Program Counter Space queue
+
+cr18: .equ     18
+
+pcoq: .equ     18                      ; Program Counter Offset queue
+
+cr19: .equ     19
+
+iir: .equ      19                      ; Interruption Instruction Register
+
+cr20: .equ     20
+
+isr: .equ      20                      ; Interruption Space Register
+
+cr21: .equ     21
+
+ior: .equ      21                      ; Interruption Offset Register
+
+cr22: .equ     22
+
+ipsw: .equ     22                      ; Interrpution Processor Status Word
+
+cr23: .equ     23
+
+eirr: .equ     23                      ; External Interrupt Request
+
+cr24: .equ     24
+
+ppda: .equ     24                      ; Physcial Page Directory Address
+
+tr0: .equ      24                      ; Temporary register 0
+
+cr25: .equ     25
+
+hta: .equ      25                      ; Hash Table Address
+
+tr1: .equ      25                      ; Temporary register 1
+
+cr26: .equ     26
+
+tr2: .equ      26                      ; Temporary register 2
+
+cr27: .equ     27
+
+tr3: .equ      27                      ; Temporary register 3
+
+cr28: .equ     28
+
+tr4: .equ      28                      ; Temporary register 4
+
+cr29: .equ     29
+
+tr5: .equ      29                      ; Temporary register 5
+
+cr30: .equ     30
+
+tr6: .equ      30                      ; Temporary register 6
+
+cr31: .equ     31
+
+tr7: .equ      31                      ; Temporary register 7
+
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+; Procedure Call Convention                                            ~
+; Register Definitions for Use with Assembler                          ~
+; version A.08.06                                                      ~
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+; Software Architecture General Registers
+rp: .equ       r2      ; return pointer
+
+mrp: .equ      r31     ; millicode return pointer
+
+ret0: .equ     r28     ; return value
+
+ret1: .equ     r29     ; return value (high part of double)
+
+sl: .equ       r29     ; static link
+
+sp: .equ       r30     ; stack pointer
+
+dp: .equ       r27     ; data pointer
+
+arg0: .equ     r26     ; argument
+
+arg1: .equ     r25     ; argument or high part of double argument
+
+arg2: .equ     r24     ; argument
+
+arg3: .equ     r23     ; argument or high part of double argument
+
+;_____________________________________________________________________________
+; Software Architecture Space Registers
+;              sr0     ; return link form BLE
+sret: .equ     sr1     ; return value
+
+sarg: .equ     sr1     ; argument
+
+;              sr4     ; PC SPACE tracker
+;              sr5     ; process private data
+;_____________________________________________________________________________
+; Software Architecture Pseudo Registers
+previous_sp: .equ      64      ; old stack pointer (locates previous frame)
+
+;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+; Standard space and subspace definitions.  version A.08.06
+; These are generally suitable for programs on HP_UX and HPE.
+; Statements commented out are used when building such things as operating
+; system kernels.
+;;;;;;;;;;;;;;;;
+; Additional code subspaces should have ALIGN=8 for an interspace BV
+; and should have SORT=24.
+;
+; For an incomplete executable (program bound to shared libraries),
+; sort keys $GLOBAL$ -1 and $GLOBAL$ -2 are reserved for the $DLT$
+; and $PLT$ subspaces respectively.
+;;;;;;;;;;;;;;;
+
+       .text
+       .EXPORT $$remI,millicode
+;      .IMPORT cerror
+$$remI:
+       .PROC
+       .CALLINFO NO_CALLS
+       .ENTRY
+       addit,= 0,arg1,r0
+       add,>= r0,arg0,ret1
+       sub r0,ret1,ret1
+       sub r0,arg1,r1
+       ds r0,r1,r0
+       or r0,r0,r1
+       add ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       ds r1,arg1,r1
+       addc ret1,ret1,ret1
+       movb,>=,n r1,ret1,remI300
+       add,< arg1,r0,r0
+       add,tr r1,arg1,ret1
+       sub r1,arg1,ret1
+remI300: add,>= arg0,r0,r0
+
+       sub r0,ret1,ret1
+       bv r0(r31)
+       nop
+       .EXIT
+       .PROCEND
+
+bit1:  .equ 1
+
+bit30: .equ 30
+bit31: .equ 31
+
+len2:  .equ 2
+
+len4:  .equ 4
+
+#if 0
+$$dyncall:
+       .proc
+       .callinfo NO_CALLS
+       .export $$dyncall,MILLICODE
+
+       bb,>=,n 22,bit30,noshlibs
+
+       depi    0,bit31,len2,22
+       ldw     4(22),19
+       ldw     0(22),22
+noshlibs:
+       ldsid   (22),r1
+       mtsp    r1,sr0
+       be      0(sr0,r22)
+       stw     rp,-24(sp)
+       .procend
+#endif
+
+$$sh_func_adrs:
+       .proc
+       .callinfo NO_CALLS
+       .export $$sh_func_adrs, millicode
+       ldo     0(r26),ret1
+       dep     r0,30,1,r26
+       probew  (r26),r31,r22
+       extru,= r22,31,1,r22
+       bv      r0(r31)
+       ldws    0(r26),ret1
+       .procend
+
+temp: .EQU     r1
+
+retreg: .EQU   ret1    ; r29
+
+       .export $$divU,millicode
+       .import $$divU_3,millicode
+       .import $$divU_5,millicode
+       .import $$divU_6,millicode
+       .import $$divU_7,millicode
+       .import $$divU_9,millicode
+       .import $$divU_10,millicode
+       .import $$divU_12,millicode
+       .import $$divU_14,millicode
+       .import $$divU_15,millicode
+$$divU:
+       .proc
+       .callinfo NO_CALLS
+; The subtract is not nullified since it does no harm and can be used
+; by the two cases that branch back to "normal".
+       comib,>=  15,arg1,special_divisor
+       sub     r0,arg1,temp            ; clear carry, negate the divisor
+       ds      r0,temp,r0              ; set V-bit to 1
+normal:
+       add     arg0,arg0,retreg        ; shift msb bit into carry
+       ds      r0,arg1,temp            ; 1st divide step, if no carry
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 2nd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 3rd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 4th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 5th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 6th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 7th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 8th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 9th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 10th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 11th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 12th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 13th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 14th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 15th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 16th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 17th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 18th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 19th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 20th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 21st divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 22nd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 23rd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 24th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 25th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 26th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 27th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 28th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 29th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 30th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 31st divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 32nd divide step,
+       bv      0(r31)
+       addc    retreg,retreg,retreg    ; shift last retreg bit into retreg
+;_____________________________________________________________________________
+; handle the cases where divisor is a small constant or has high bit on
+special_divisor:
+       blr     arg1,r0
+       comib,>,n  0,arg1,big_divisor   ; nullify previous instruction
+zero_divisor: ; this label is here to provide external visibility
+
+       addit,= 0,arg1,0                ; trap for zero dvr
+       nop
+       bv      0(r31)                  ; divisor == 1
+       copy    arg0,retreg
+       bv      0(r31)                  ; divisor == 2
+       extru   arg0,30,31,retreg
+        b,n    $$divU_3                ; divisor == 3
+       nop
+       bv      0(r31)                  ; divisor == 4
+       extru   arg0,29,30,retreg
+        b,n    $$divU_5                ; divisor == 5
+       nop
+        b,n    $$divU_6                ; divisor == 6
+       nop
+        b,n    $$divU_7                ; divisor == 7
+       nop
+       bv      0(r31)                  ; divisor == 8
+       extru   arg0,28,29,retreg
+        b,n    $$divU_9                ; divisor == 9
+       nop
+        b,n    $$divU_10               ; divisor == 10
+       nop
+       b       normal                  ; divisor == 11
+       ds      r0,temp,r0              ; set V-bit to 1
+        b,n    $$divU_12               ; divisor == 12
+       nop
+       b       normal                  ; divisor == 13
+       ds      r0,temp,r0              ; set V-bit to 1
+        b,n    $$divU_14               ; divisor == 14
+       nop
+        b,n    $$divU_15               ; divisor == 15
+       nop
+;_____________________________________________________________________________
+; Handle the case where the high bit is on in the divisor.
+; Compute:     if( dividend>=divisor) quotient=1; else quotient=0;
+; Note:                dividend>==divisor iff dividend-divisor does not borrow
+; and          not borrow iff carry
+big_divisor:
+       sub     arg0,arg1,r0
+       bv      0(r31)
+       addc    r0,r0,retreg
+       .procend
+       .end
+
+t2: .EQU       r1
+
+; x2   .EQU    arg0    ; r26
+t1: .EQU       arg1    ; r25
+
+; x1   .EQU    ret1    ; r29
+;_____________________________________________________________________________
+
+$$divide_by_constant:
+       .PROC
+       .CALLINFO NO_CALLS
+       .export $$divide_by_constant,millicode
+; Provides a "nice" label for the code covered by the unwind descriptor
+; for things like gprof.
+
+$$divI_2:
+       .EXPORT $$divI_2,MILLICODE
+       COMCLR,>=       arg0,0,0
+       ADDI            1,arg0,arg0
+       bv              0(r31)
+       EXTRS           arg0,30,31,ret1
+
+$$divI_4:
+       .EXPORT         $$divI_4,MILLICODE
+       COMCLR,>=       arg0,0,0
+       ADDI            3,arg0,arg0
+       bv              0(r31)
+       EXTRS           arg0,29,30,ret1
+
+$$divI_8:
+       .EXPORT         $$divI_8,MILLICODE
+       COMCLR,>=       arg0,0,0
+       ADDI            7,arg0,arg0
+       bv              0(r31)
+       EXTRS           arg0,28,29,ret1
+
+$$divI_16:
+       .EXPORT         $$divI_16,MILLICODE
+       COMCLR,>=       arg0,0,0
+       ADDI            15,arg0,arg0
+       bv              0(r31)
+       EXTRS           arg0,27,28,ret1
+
+$$divI_3:
+       .EXPORT         $$divI_3,MILLICODE
+       COMB,<,N        arg0,0,$neg3
+
+       ADDI            1,arg0,arg0
+       EXTRU           arg0,1,2,ret1
+       SH2ADD          arg0,arg0,arg0
+       B               $pos
+       ADDC            ret1,0,ret1
+
+$neg3:
+       SUBI            1,arg0,arg0
+       EXTRU           arg0,1,2,ret1
+       SH2ADD          arg0,arg0,arg0
+       B               $neg
+       ADDC            ret1,0,ret1
+
+$$divU_3:
+       .EXPORT         $$divU_3,MILLICODE
+       ADDI            1,arg0,arg0
+       ADDC            0,0,ret1
+       SHD             ret1,arg0,30,t1
+       SH2ADD          arg0,arg0,arg0
+       B               $pos
+       ADDC            ret1,t1,ret1
+
+$$divI_5:
+       .EXPORT         $$divI_5,MILLICODE
+       COMB,<,N        arg0,0,$neg5
+       ADDI            3,arg0,t1
+       SH1ADD          arg0,t1,arg0
+       B               $pos
+       ADDC            0,0,ret1
+
+$neg5:
+       SUB             0,arg0,arg0
+       ADDI            1,arg0,arg0
+       SHD             0,arg0,31,ret1
+       SH1ADD          arg0,arg0,arg0
+       B               $neg
+       ADDC            ret1,0,ret1
+
+$$divU_5:
+       .EXPORT         $$divU_5,MILLICODE
+       ADDI            1,arg0,arg0
+       ADDC            0,0,ret1
+       SHD             ret1,arg0,31,t1
+       SH1ADD          arg0,arg0,arg0
+       B               $pos
+       ADDC            t1,ret1,ret1
+
+$$divI_6:
+       .EXPORT         $$divI_6,MILLICODE
+       COMB,<,N        arg0,0,$neg6
+       EXTRU           arg0,30,31,arg0
+       ADDI            5,arg0,t1
+       SH2ADD          arg0,t1,arg0
+       B               $pos
+       ADDC            0,0,ret1
+
+$neg6:
+       SUBI            2,arg0,arg0
+       EXTRU           arg0,30,31,arg0
+       SHD             0,arg0,30,ret1
+       SH2ADD          arg0,arg0,arg0
+       B               $neg
+       ADDC            ret1,0,ret1
+
+$$divU_6:
+       .EXPORT         $$divU_6,MILLICODE
+       EXTRU           arg0,30,31,arg0
+       ADDI            1,arg0,arg0
+       SHD             0,arg0,30,ret1
+       SH2ADD          arg0,arg0,arg0
+       B               $pos
+       ADDC            ret1,0,ret1
+
+$$divU_10:
+       .EXPORT         $$divU_10,MILLICODE
+       EXTRU           arg0,30,31,arg0
+       ADDI            3,arg0,t1
+       SH1ADD          arg0,t1,arg0
+       ADDC            0,0,ret1
+$pos:
+       SHD             ret1,arg0,28,t1
+       SHD             arg0,0,28,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+$pos_for_17:
+       SHD             ret1,arg0,24,t1
+       SHD             arg0,0,24,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+
+       SHD             ret1,arg0,16,t1
+       SHD             arg0,0,16,t2
+       ADD             arg0,t2,arg0
+       bv              0(r31)
+       ADDC            ret1,t1,ret1
+
+$$divI_10:
+       .EXPORT         $$divI_10,MILLICODE
+       COMB,<          arg0,0,$neg10
+       COPY            0,ret1
+       EXTRU           arg0,30,31,arg0
+       ADDIB,TR        1,arg0,$pos
+       SH1ADD          arg0,arg0,arg0
+
+$neg10:
+       SUBI            2,arg0,arg0
+       EXTRU           arg0,30,31,arg0
+       SH1ADD          arg0,arg0,arg0
+$neg:
+       SHD             ret1,arg0,28,t1
+       SHD             arg0,0,28,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+$neg_for_17:
+       SHD             ret1,arg0,24,t1
+       SHD             arg0,0,24,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+
+       SHD             ret1,arg0,16,t1
+       SHD             arg0,0,16,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+       bv              0(r31)
+       SUB             0,ret1,ret1
+
+$$divI_12:
+       .EXPORT         $$divI_12,MILLICODE
+       COMB,<          arg0,0,$neg12
+       COPY            0,ret1
+       EXTRU           arg0,29,30,arg0
+       ADDIB,TR        1,arg0,$pos
+       SH2ADD          arg0,arg0,arg0
+
+$neg12:
+       SUBI            4,arg0,arg0
+       EXTRU           arg0,29,30,arg0
+       B               $neg
+       SH2ADD          arg0,arg0,arg0
+
+$$divU_12:
+       .EXPORT         $$divU_12,MILLICODE
+       EXTRU           arg0,29,30,arg0
+       ADDI            5,arg0,t1
+       SH2ADD          arg0,t1,arg0
+       B               $pos
+       ADDC            0,0,ret1
+
+$$divI_15:
+       .EXPORT         $$divI_15,MILLICODE
+       COMB,<          arg0,0,$neg15
+       COPY            0,ret1
+       ADDIB,TR        1,arg0,$pos+4
+       SHD             ret1,arg0,28,t1
+
+$neg15:
+       B               $neg
+       SUBI            1,arg0,arg0
+
+$$divU_15:
+       .EXPORT         $$divU_15,MILLICODE
+       ADDI            1,arg0,arg0
+       B               $pos
+       ADDC            0,0,ret1
+
+$$divI_17:
+       .EXPORT         $$divI_17,MILLICODE
+       COMB,<,N        arg0,0,$neg17
+       ADDI            1,arg0,arg0
+       SHD             0,arg0,28,t1
+       SHD             arg0,0,28,t2
+       SUB             t2,arg0,arg0
+       B               $pos_for_17
+       SUBB            t1,0,ret1
+
+$neg17:
+       SUBI            1,arg0,arg0
+       SHD             0,arg0,28,t1
+       SHD             arg0,0,28,t2
+       SUB             t2,arg0,arg0
+       B               $neg_for_17
+       SUBB            t1,0,ret1
+
+$$divU_17:
+       .EXPORT         $$divU_17,MILLICODE
+       ADDI            1,arg0,arg0
+       ADDC            0,0,ret1
+       SHD             ret1,arg0,28,t1
+$u17:
+       SHD             arg0,0,28,t2
+       SUB             t2,arg0,arg0
+       B               $pos_for_17
+       SUBB            t1,ret1,ret1
+
+$$divI_7:
+       .EXPORT         $$divI_7,MILLICODE
+       COMB,<,N        arg0,0,$neg7
+$7:
+       ADDI            1,arg0,arg0
+       SHD             0,arg0,29,ret1
+       SH3ADD          arg0,arg0,arg0
+       ADDC            ret1,0,ret1
+$pos7:
+       SHD             ret1,arg0,26,t1
+       SHD             arg0,0,26,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+
+       SHD             ret1,arg0,20,t1
+       SHD             arg0,0,20,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,t1
+
+       COPY            0,ret1
+       SHD,=           t1,arg0,24,t1
+$1:
+       ADDB,TR         t1,ret1,$2
+       EXTRU           arg0,31,24,arg0
+
+       bv,n  0(r31)
+
+$2:
+       ADDB,TR         t1,arg0,$1
+       EXTRU,=         arg0,7,8,t1
+
+$neg7:
+       SUBI            1,arg0,arg0
+$8:
+       SHD             0,arg0,29,ret1
+       SH3ADD          arg0,arg0,arg0
+       ADDC            ret1,0,ret1
+
+$neg7_shift:
+       SHD             ret1,arg0,26,t1
+       SHD             arg0,0,26,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,ret1
+
+       SHD             ret1,arg0,20,t1
+       SHD             arg0,0,20,t2
+       ADD             arg0,t2,arg0
+       ADDC            ret1,t1,t1
+
+       COPY            0,ret1
+       SHD,=           t1,arg0,24,t1
+$3:
+       ADDB,TR         t1,ret1,$4
+       EXTRU           arg0,31,24,arg0
+
+       bv              0(r31)
+       SUB             0,ret1,ret1
+
+$4:
+       ADDB,TR         t1,arg0,$3
+       EXTRU,=         arg0,7,8,t1
+
+$$divU_7:
+       .EXPORT         $$divU_7,MILLICODE
+       ADDI            1,arg0,arg0
+       ADDC            0,0,ret1
+       SHD             ret1,arg0,29,t1
+       SH3ADD          arg0,arg0,arg0
+       B               $pos7
+       ADDC            t1,ret1,ret1
+
+$$divI_9:
+       .EXPORT         $$divI_9,MILLICODE
+       COMB,<,N        arg0,0,$neg9
+       ADDI            1,arg0,arg0
+       SHD             0,arg0,29,t1
+       SHD             arg0,0,29,t2
+       SUB             t2,arg0,arg0
+       B               $pos7
+       SUBB            t1,0,ret1
+
+$neg9:
+       SUBI            1,arg0,arg0
+       SHD             0,arg0,29,t1
+       SHD             arg0,0,29,t2
+       SUB             t2,arg0,arg0
+       B               $neg7_shift
+       SUBB            t1,0,ret1
+
+$$divU_9:
+       .EXPORT         $$divU_9,MILLICODE
+       ADDI            1,arg0,arg0
+       ADDC            0,0,ret1
+       SHD             ret1,arg0,29,t1
+       SHD             arg0,0,29,t2
+       SUB             t2,arg0,arg0
+       B               $pos7
+       SUBB            t1,ret1,ret1
+
+$$divI_14:
+       .EXPORT         $$divI_14,MILLICODE
+       COMB,<,N        arg0,0,$neg14
+$$divU_14:
+       .EXPORT         $$divU_14,MILLICODE
+       B               $7
+       EXTRU           arg0,30,31,arg0
+
+$neg14:
+       SUBI            2,arg0,arg0
+       B               $8
+       EXTRU           arg0,30,31,arg0
+
+       .PROCEND
+       .END
+
+rmndr: .EQU    ret1    ; r29
+
+       .export $$remU,millicode
+$$remU:
+       .proc
+       .callinfo NO_CALLS
+       .entry
+
+       comib,>=,n  0,arg1,special_case
+       sub     r0,arg1,rmndr           ; clear carry, negate the divisor
+       ds      r0,rmndr,r0             ; set V-bit to 1
+       add     arg0,arg0,temp          ; shift msb bit into carry
+       ds      r0,arg1,rmndr           ; 1st divide step, if no carry
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 2nd divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 3rd divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 4th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 5th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 6th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 7th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 8th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 9th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 10th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 11th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 12th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 13th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 14th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 15th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 16th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 17th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 18th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 19th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 20th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 21st divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 22nd divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 23rd divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 24th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 25th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 26th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 27th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 28th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 29th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 30th divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 31st divide step
+       addc    temp,temp,temp          ; shift temp with/into carry
+       ds      rmndr,arg1,rmndr                ; 32nd divide step,
+       comiclr,<= 0,rmndr,r0
+         add   rmndr,arg1,rmndr        ; correction
+;      .exit
+       bv,n  0(r31)
+       nop
+; Putting >= on the last DS and deleting COMICLR does not work!
+;_____________________________________________________________________________
+special_case:
+       addit,= 0,arg1,r0               ; trap on div by zero
+       sub,>>= arg0,arg1,rmndr
+         copy  arg0,rmndr
+       .exit
+       bv,n  0(r31)
+       nop
+       .procend
+       .end
+
+; Use bv  0(r31) and bv,n  0(r31) instead.
+; #define      return          bv      0(%mrp)
+; #define      return_n        bv,n    0(%mrp)
+
+       .align 16
+$$mulI:
+
+       .proc
+       .callinfo NO_CALLS
+       .export $$mulI, millicode
+       combt,<<=       %r25,%r26,l4    ; swap args if unsigned %r25>%r26
+       copy            0,%r29          ; zero out the result
+       xor             %r26,%r25,%r26  ; swap %r26 & %r25 using the
+       xor             %r26,%r25,%r25  ;  old xor trick
+       xor             %r26,%r25,%r26
+l4: combt,<=   0,%r26,l3               ; if %r26>=0 then proceed like unsigned
+
+       zdep            %r25,30,8,%r1   ; %r1 = (%r25&0xff)<<1 *********
+       sub,>           0,%r25,%r1              ; otherwise negate both and
+       combt,<=,n      %r26,%r1,l2     ;  swap back if |%r26|<|%r25|
+       sub             0,%r26,%r25
+       movb,tr,n       %r1,%r26,l2     ; 10th inst.
+
+l0:    add     %r29,%r1,%r29                           ; add in this partial product
+
+l1: zdep       %r26,23,24,%r26                 ; %r26 <<= 8 ******************
+
+l2: zdep               %r25,30,8,%r1   ; %r1 = (%r25&0xff)<<1 *********
+
+l3: blr                %r1,0           ; case on these 8 bits ******
+
+       extru           %r25,23,24,%r25 ; %r25 >>= 8 ******************
+
+;16 insts before this.
+;                        %r26 <<= 8 **************************
+x0: comb,<>    %r25,0,l2       ! zdep  %r26,23,24,%r26 ! bv,n  0(r31)  ! nop
+
+x1: comb,<>    %r25,0,l1       !       add     %r29,%r26,%r29  ! bv,n  0(r31)  ! nop
+
+x2: comb,<>    %r25,0,l1       ! sh1add        %r26,%r29,%r29  ! bv,n  0(r31)  ! nop
+
+x3: comb,<>    %r25,0,l0       !       sh1add  %r26,%r26,%r1   ! bv    0(r31)  !       add     %r29,%r1,%r29
+
+x4: comb,<>    %r25,0,l1       ! sh2add        %r26,%r29,%r29  ! bv,n  0(r31)  ! nop
+
+x5: comb,<>    %r25,0,l0       !       sh2add  %r26,%r26,%r1   ! bv    0(r31)  !       add     %r29,%r1,%r29
+
+x6:    sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh1add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x7:    sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh2add        %r26,%r29,%r29  ! b,n   ret_t0
+
+x8: comb,<>    %r25,0,l1       ! sh3add        %r26,%r29,%r29  ! bv,n  0(r31)  ! nop
+
+x9: comb,<>    %r25,0,l0       !       sh3add  %r26,%r26,%r1   ! bv    0(r31)  !       add     %r29,%r1,%r29
+
+x10:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh1add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x11:   sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh3add        %r26,%r29,%r29  ! b,n   ret_t0
+
+x12:   sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh2add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x13:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh3add        %r26,%r29,%r29  ! b,n   ret_t0
+
+x14:   sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x15:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       !       sh1add  %r1,%r1,%r1     ! b,n   ret_t0
+
+x16: zdep      %r26,27,28,%r1  ! comb,<>       %r25,0,l1       !       add     %r29,%r1,%r29   ! bv,n  0(r31)
+
+x17:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh3add        %r26,%r1,%r1    ! b,n   ret_t0
+
+x18:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh1add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x19:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh1add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x20:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh2add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x21:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh2add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x22:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x23:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x24:   sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh3add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x25:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       !       sh2add  %r1,%r1,%r1     ! b,n   ret_t0
+
+x26:   sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x27:   sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       !       sh3add  %r1,%r1,%r1     ! b,n   ret_t0
+
+x28:   sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x29:   sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x30:   sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x31: zdep      %r26,26,27,%r1  ! comb,<>       %r25,0,l0       ! sub   %r1,%r26,%r1    ! b,n   ret_t0
+
+x32: zdep      %r26,26,27,%r1  ! comb,<>       %r25,0,l1       !       add     %r29,%r1,%r29   ! bv,n  0(r31)
+
+x33:   sh3add  %r26,0,%r1              ! comb,<>       %r25,0,l0       ! sh2add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x34: zdep      %r26,27,28,%r1  ! add   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x35:   sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh3add        %r26,%r1,%r1
+
+x36:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh2add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x37:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh2add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x38:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x39:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x40:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh3add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x41:   sh2add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! sh3add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x42:   sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x43:   sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x44:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x45:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       !       sh2add  %r1,%r1,%r1     ! b,n   ret_t0
+
+x46:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! add   %r1,%r26,%r1
+
+x47:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh1add        %r26,%r1,%r1
+
+x48:   sh1add  %r26,%r26,%r1           ! comb,<>       %r25,0,l0       ! zdep  %r1,27,28,%r1   ! b,n   ret_t0
+
+x49:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r26,%r1,%r1
+
+x50:   sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x51:   sh3add  %r26,%r26,%r1           ! sh3add        %r26,%r1,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x52:   sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x53:   sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x54:   sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x55:   sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x56:   sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x57:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x58:   sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x59:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_t02a0 !       sh1add  %r1,%r1,%r1
+
+x60:   sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x61:   sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x62: zdep      %r26,26,27,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x63: zdep      %r26,25,26,%r1  ! comb,<>       %r25,0,l0       ! sub   %r1,%r26,%r1    ! b,n   ret_t0
+
+x64: zdep      %r26,25,26,%r1  ! comb,<>       %r25,0,l1       !       add     %r29,%r1,%r29   ! bv,n  0(r31)
+
+x65:   sh3add  %r26,0,%r1              ! comb,<>       %r25,0,l0       ! sh3add        %r1,%r26,%r1    ! b,n   ret_t0
+
+x66: zdep      %r26,26,27,%r1  ! add   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x67:   sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x68:   sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x69:   sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x70: zdep      %r26,25,26,%r1  ! sh2add        %r26,%r1,%r1    !       b       e_t0    ! sh1add        %r26,%r1,%r1
+
+x71:   sh3add  %r26,%r26,%r1           !       sh3add  %r1,0,%r1       !       b       e_t0    ! sub   %r1,%r26,%r1
+
+x72:   sh3add  %r26,%r26,%r1           ! comb,<>       %r25,0,l1       ! sh3add        %r1,%r29,%r29   ! bv,n  0(r31)
+
+x73:   sh3add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_shift !       add     %r29,%r1,%r29
+
+x74:   sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x75:   sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x76:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x77:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x78:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x79: zdep      %r26,27,28,%r1  !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sub   %r1,%r26,%r1
+
+x80: zdep      %r26,27,28,%r1  !       sh2add  %r1,%r1,%r1     ! b     e_shift !       add     %r29,%r1,%r29
+
+x81:   sh3add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     ! b     e_shift !       add     %r29,%r1,%r29
+
+x82:   sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x83:   sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x84:   sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x85:   sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x86:   sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x87:   sh3add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     ! b     e_t02a0 ! sh2add        %r26,%r1,%r1
+
+x88:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x89:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x90:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x91:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x92:   sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_4t0   ! sh1add        %r1,%r26,%r1
+
+x93: zdep      %r26,26,27,%r1  ! sub   %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x94:   sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_2t0   ! sh1add        %r26,%r1,%r1
+
+x95:   sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x96:   sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x97:   sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x98: zdep      %r26,26,27,%r1  !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh1add        %r26,%r1,%r1
+
+x99:   sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x100:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x101:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x102: zdep     %r26,26,27,%r1  ! sh1add        %r26,%r1,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x103:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_t02a0 ! sh2add        %r1,%r26,%r1
+
+x104:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x105:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x106:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x107:  sh3add  %r26,%r26,%r1           ! sh2add        %r26,%r1,%r1    ! b     e_t02a0 ! sh3add        %r1,%r26,%r1
+
+x108:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x109:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x110:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x111:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x112:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! zdep  %r1,27,28,%r1
+
+x113:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_t02a0 !       sh1add  %r1,%r1,%r1
+
+x114:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   !       sh1add  %r1,%r1,%r1
+
+x115:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh1add  %r1,%r1,%r1
+
+x116:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_4t0   ! sh2add        %r1,%r26,%r1
+
+x117:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh3add  %r1,%r1,%r1
+
+x118:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_t0a0  !       sh3add  %r1,%r1,%r1
+
+x119:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_t02a0 !       sh3add  %r1,%r1,%r1
+
+x120:  sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x121:  sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x122:  sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x123:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x124: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x125:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x126: zdep     %r26,25,26,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x127: zdep     %r26,24,25,%r1  ! comb,<>       %r25,0,l0       ! sub   %r1,%r26,%r1    ! b,n   ret_t0
+
+x128: zdep     %r26,24,25,%r1  ! comb,<>       %r25,0,l1       !       add     %r29,%r1,%r29   ! bv,n  0(r31)
+
+x129: zdep     %r26,24,25,%r1  ! comb,<>       %r25,0,l0       ! add   %r1,%r26,%r1    ! b,n   ret_t0
+
+x130: zdep     %r26,25,26,%r1  ! add   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x131:  sh3add  %r26,0,%r1              ! sh3add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x132:  sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x133:  sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x134:  sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x135:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x136:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x137:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x138:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x139:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    ! b     e_2t0a0 ! sh2add        %r1,%r26,%r1
+
+x140:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_4t0   !       sh2add  %r1,%r1,%r1
+
+x141:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    ! b     e_4t0a0 ! sh1add        %r1,%r26,%r1
+
+x142:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,0,%r1       !       b       e_2t0   ! sub   %r1,%r26,%r1
+
+x143: zdep     %r26,27,28,%r1  !       sh3add  %r1,%r1,%r1     !       b       e_t0    ! sub   %r1,%r26,%r1
+
+x144:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,0,%r1       ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x145:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,0,%r1       !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x146:  sh3add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x147:  sh3add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x148:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x149:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x150:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x151:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_2t0a0 ! sh1add        %r1,%r26,%r1
+
+x152:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x153:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x154:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x155: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x156:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_4t0   ! sh1add        %r1,%r26,%r1
+
+x157: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    ! b     e_t02a0 !       sh2add  %r1,%r1,%r1
+
+x158: zdep     %r26,27,28,%r1  !       sh2add  %r1,%r1,%r1     !       b       e_2t0   ! sub   %r1,%r26,%r1
+
+x159: zdep     %r26,26,27,%r1  !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sub   %r1,%r26,%r1
+
+x160:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,0,%r1       ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x161:  sh3add  %r26,0,%r1              !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x162:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x163:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     !       b       e_t0    ! sh1add        %r1,%r26,%r1
+
+x164:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x165:  sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x166:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x167:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_2t0a0 ! sh1add        %r1,%r26,%r1
+
+x168:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x169:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x170: zdep     %r26,26,27,%r1  ! sh1add        %r26,%r1,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x171:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_t0    !       sh3add  %r1,%r1,%r1
+
+x172:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_4t0   ! sh1add        %r1,%r26,%r1
+
+x173:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_t02a0 !       sh3add  %r1,%r1,%r1
+
+x174: zdep     %r26,26,27,%r1  ! sh1add        %r26,%r1,%r1    ! b     e_t04a0 !       sh2add  %r1,%r1,%r1
+
+x175:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_5t0   ! sh1add        %r1,%r26,%r1
+
+x176:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_8t0   ! add   %r1,%r26,%r1
+
+x177:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_8t0a0 ! add   %r1,%r26,%r1
+
+x178:  sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   ! sh3add        %r1,%r26,%r1
+
+x179:  sh2add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_2t0a0 ! sh3add        %r1,%r26,%r1
+
+x180:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x181:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x182:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_2t0   ! sh1add        %r1,%r26,%r1
+
+x183:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_2t0a0 ! sh1add        %r1,%r26,%r1
+
+x184:  sh2add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     !       b       e_4t0   ! add   %r1,%r26,%r1
+
+x185:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x186: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    !       b       e_2t0   !       sh1add  %r1,%r1,%r1
+
+x187:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_t02a0 !       sh2add  %r1,%r1,%r1
+
+x188:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_4t0   ! sh1add        %r26,%r1,%r1
+
+x189:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_t0    !       sh3add  %r1,%r1,%r1
+
+x190:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_2t0   !       sh2add  %r1,%r1,%r1
+
+x191: zdep     %r26,25,26,%r1  !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sub   %r1,%r26,%r1
+
+x192:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x193:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x194:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x195:  sh3add  %r26,0,%r1              ! sh3add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x196:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     !       b       e_4t0   ! sh1add        %r1,%r26,%r1
+
+x197:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     ! b     e_4t0a0 ! sh1add        %r1,%r26,%r1
+
+x198: zdep     %r26,25,26,%r1  ! sh1add        %r26,%r1,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x199:  sh3add  %r26,0,%r1              ! sh2add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh1add  %r1,%r1,%r1
+
+x200:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x201:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x202:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x203:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_2t0a0 ! sh2add        %r1,%r26,%r1
+
+x204:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_4t0   !       sh1add  %r1,%r1,%r1
+
+x205:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x206: zdep     %r26,25,26,%r1  ! sh2add        %r26,%r1,%r1    ! b     e_t02a0 !       sh1add  %r1,%r1,%r1
+
+x207:  sh3add  %r26,0,%r1              ! sh1add        %r1,%r26,%r1    !       b       e_3t0   ! sh2add        %r1,%r26,%r1
+
+x208:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_8t0   ! add   %r1,%r26,%r1
+
+x209:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_8t0a0 ! add   %r1,%r26,%r1
+
+x210:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   !       sh2add  %r1,%r1,%r1
+
+x211:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh2add  %r1,%r1,%r1
+
+x212:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_4t0   ! sh2add        %r1,%r26,%r1
+
+x213:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_4t0a0 ! sh2add        %r1,%r26,%r1
+
+x214:  sh3add  %r26,%r26,%r1           ! sh2add        %r26,%r1,%r1    ! b     e2t04a0 ! sh3add        %r1,%r26,%r1
+
+x215:  sh2add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_5t0   ! sh1add        %r1,%r26,%r1
+
+x216:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x217:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x218:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_2t0   ! sh2add        %r1,%r26,%r1
+
+x219:  sh3add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x220:  sh1add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     !       b       e_4t0   ! sh1add        %r1,%r26,%r1
+
+x221:  sh1add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     ! b     e_4t0a0 ! sh1add        %r1,%r26,%r1
+
+x222:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   !       sh1add  %r1,%r1,%r1
+
+x223:  sh3add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh1add  %r1,%r1,%r1
+
+x224:  sh3add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_8t0   ! add   %r1,%r26,%r1
+
+x225:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_t0    !       sh2add  %r1,%r1,%r1
+
+x226:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_t02a0 ! zdep  %r1,26,27,%r1
+
+x227:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_t02a0 !       sh2add  %r1,%r1,%r1
+
+x228:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_4t0   !       sh1add  %r1,%r1,%r1
+
+x229:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_4t0a0 !       sh1add  %r1,%r1,%r1
+
+x230:  sh3add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_5t0   ! add   %r1,%r26,%r1
+
+x231:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_3t0   ! sh2add        %r1,%r26,%r1
+
+x232:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    !       b       e_8t0   ! sh2add        %r1,%r26,%r1
+
+x233:  sh1add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e_8t0a0 ! sh2add        %r1,%r26,%r1
+
+x234:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    !       b       e_2t0   !       sh3add  %r1,%r1,%r1
+
+x235:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh3add  %r1,%r1,%r1
+
+x236:  sh3add  %r26,%r26,%r1           ! sh1add        %r1,%r26,%r1    ! b     e4t08a0 !       sh1add  %r1,%r1,%r1
+
+x237: zdep     %r26,27,28,%r1  !       sh2add  %r1,%r1,%r1     !       b       e_3t0   ! sub   %r1,%r26,%r1
+
+x238:  sh1add  %r26,%r26,%r1           ! sh2add        %r1,%r26,%r1    ! b     e2t04a0 !       sh3add  %r1,%r1,%r1
+
+x239: zdep     %r26,27,28,%r1  !       sh2add  %r1,%r1,%r1     ! b     e_t0ma0 !       sh1add  %r1,%r1,%r1
+
+x240:  sh3add  %r26,%r26,%r1           ! add   %r1,%r26,%r1    !       b       e_8t0   !       sh1add  %r1,%r1,%r1
+
+x241:  sh3add  %r26,%r26,%r1           ! add   %r1,%r26,%r1    ! b     e_8t0a0 !       sh1add  %r1,%r1,%r1
+
+x242:  sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_2t0   ! sh3add        %r1,%r26,%r1
+
+x243:  sh3add  %r26,%r26,%r1           !       sh3add  %r1,%r1,%r1     !       b       e_t0    !       sh1add  %r1,%r1,%r1
+
+x244:  sh2add  %r26,%r26,%r1           !       sh1add  %r1,%r1,%r1     !       b       e_4t0   ! sh2add        %r1,%r26,%r1
+
+x245:  sh3add  %r26,0,%r1              !       sh1add  %r1,%r1,%r1     !       b       e_5t0   ! sh1add        %r1,%r26,%r1
+
+x246:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    !       b       e_2t0   !       sh1add  %r1,%r1,%r1
+
+x247:  sh2add  %r26,%r26,%r1           ! sh3add        %r1,%r26,%r1    ! b     e_2t0a0 !       sh1add  %r1,%r1,%r1
+
+x248: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh3add        %r1,%r29,%r29
+
+x249: zdep     %r26,26,27,%r1  ! sub   %r1,%r26,%r1    !       b       e_t0    ! sh3add        %r1,%r26,%r1
+
+x250:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     !       b       e_2t0   !       sh2add  %r1,%r1,%r1
+
+x251:  sh2add  %r26,%r26,%r1           !       sh2add  %r1,%r1,%r1     ! b     e_2t0a0 !       sh2add  %r1,%r1,%r1
+
+x252: zdep     %r26,25,26,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh2add        %r1,%r29,%r29
+
+x253: zdep     %r26,25,26,%r1  ! sub   %r1,%r26,%r1    !       b       e_t0    ! sh2add        %r1,%r26,%r1
+
+x254: zdep     %r26,24,25,%r1  ! sub   %r1,%r26,%r1    ! b     e_shift ! sh1add        %r1,%r29,%r29
+
+x255: zdep     %r26,23,24,%r1  ! comb,<>       %r25,0,l0       ! sub   %r1,%r26,%r1    ! b,n   ret_t0
+
+;1040 insts before this.
+ret_t0: bv     0(r31)
+
+e_t0:  add     %r29,%r1,%r29
+
+e_shift: comb,<>       %r25,0,l2
+
+       zdep    %r26,23,24,%r26 ; %r26 <<= 8 ***********
+       bv,n  0(r31)
+e_t0ma0: comb,<>       %r25,0,l0
+
+       sub     %r1,%r26,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_t0a0: comb,<>        %r25,0,l0
+
+       add     %r1,%r26,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_t02a0: comb,<>       %r25,0,l0
+
+       sh1add  %r26,%r1,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_t04a0: comb,<>       %r25,0,l0
+
+       sh2add  %r26,%r1,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_2t0: comb,<> %r25,0,l1
+
+       sh1add  %r1,%r29,%r29
+       bv,n  0(r31)
+e_2t0a0: comb,<>       %r25,0,l0
+
+       sh1add  %r1,%r26,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e2t04a0: sh1add        %r26,%r1,%r1
+
+       comb,<> %r25,0,l1
+       sh1add  %r1,%r29,%r29
+       bv,n  0(r31)
+e_3t0: comb,<> %r25,0,l0
+
+       sh1add  %r1,%r1,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_4t0: comb,<> %r25,0,l1
+
+       sh2add  %r1,%r29,%r29
+       bv,n  0(r31)
+e_4t0a0: comb,<>       %r25,0,l0
+
+       sh2add  %r1,%r26,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e4t08a0: sh1add        %r26,%r1,%r1
+
+       comb,<> %r25,0,l1
+       sh2add  %r1,%r29,%r29
+       bv,n  0(r31)
+e_5t0: comb,<> %r25,0,l0
+
+       sh2add  %r1,%r1,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+e_8t0: comb,<> %r25,0,l1
+
+       sh3add  %r1,%r29,%r29
+       bv,n  0(r31)
+e_8t0a0: comb,<>       %r25,0,l0
+
+       sh3add  %r1,%r26,%r1
+       bv      0(r31)
+       add     %r29,%r1,%r29
+
+       .procend
+       .end
+
+       .import $$divI_2,millicode
+       .import $$divI_3,millicode
+       .import $$divI_4,millicode
+       .import $$divI_5,millicode
+       .import $$divI_6,millicode
+       .import $$divI_7,millicode
+       .import $$divI_8,millicode
+       .import $$divI_9,millicode
+       .import $$divI_10,millicode
+       .import $$divI_12,millicode
+       .import $$divI_14,millicode
+       .import $$divI_15,millicode
+       .export $$divI,millicode
+       .export $$divoI,millicode
+$$divoI:
+       .proc
+       .callinfo       NO_CALLS
+       comib,=,n  -1,arg1,negative1    ; when divisor == -1
+$$divI:
+       comib,>>=,n 15,arg1,small_divisor
+       add,>=  0,arg0,retreg           ; move dividend, if retreg < 0,
+normal1:
+         sub   0,retreg,retreg         ;   make it positive
+       sub     0,arg1,temp             ; clear carry,
+                                       ;   negate the divisor
+       ds      0,temp,0                ; set V-bit to the comple-
+                                       ;   ment of the divisor sign
+       add     retreg,retreg,retreg    ; shift msb bit into carry
+       ds      r0,arg1,temp            ; 1st divide step, if no carry
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 2nd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 3rd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 4th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 5th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 6th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 7th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 8th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 9th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 10th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 11th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 12th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 13th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 14th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 15th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 16th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 17th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 18th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 19th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 20th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 21st divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 22nd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 23rd divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 24th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 25th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 26th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 27th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 28th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 29th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 30th divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 31st divide step
+       addc    retreg,retreg,retreg    ; shift retreg with/into carry
+       ds      temp,arg1,temp          ; 32nd divide step,
+       addc    retreg,retreg,retreg    ; shift last retreg bit into retreg
+       xor,>=  arg0,arg1,0             ; get correct sign of quotient
+         sub   0,retreg,retreg         ;   based on operand signs
+       bv,n  0(r31)
+       nop
+;______________________________________________________________________
+small_divisor:
+       blr,n   arg1,r0
+       nop
+; table for divisor == 0,1, ... ,15
+       addit,= 0,arg1,r0       ; trap if divisor == 0
+       nop
+       bv      0(r31)          ; divisor == 1
+       copy    arg0,retreg
+        b,n    $$divI_2        ; divisor == 2
+       nop
+        b,n    $$divI_3        ; divisor == 3
+       nop
+        b,n    $$divI_4        ; divisor == 4
+       nop
+        b,n    $$divI_5        ; divisor == 5
+       nop
+        b,n    $$divI_6        ; divisor == 6
+       nop
+        b,n    $$divI_7        ; divisor == 7
+       nop
+        b,n    $$divI_8        ; divisor == 8
+       nop
+        b,n    $$divI_9        ; divisor == 9
+       nop
+        b,n    $$divI_10       ; divisor == 10
+       nop
+       b       normal1         ; divisor == 11
+       add,>=  0,arg0,retreg
+        b,n    $$divI_12       ; divisor == 12
+       nop
+       b       normal1         ; divisor == 13
+       add,>=  0,arg0,retreg
+        b,n    $$divI_14       ; divisor == 14
+       nop
+        b,n    $$divI_15       ; divisor == 15
+       nop
+;______________________________________________________________________
+negative1:
+       sub     0,arg0,retreg   ; result is negation of dividend
+       bv      0(r31)
+       addo    arg0,arg1,r0    ; trap iff dividend==0x80000000 && divisor==-1
+       .procend
+       .end
diff --git a/sys/lib/libkern/arch/hppa/prefix.h b/sys/lib/libkern/arch/hppa/prefix.h
new file mode 100644 (file)
index 0000000..1c49a87
--- /dev/null
@@ -0,0 +1,85 @@
+/*     $NetBSD: prefix.h,v 1.1 2002/06/06 20:03:39 fredette Exp $      */
+
+/*     $OpenBSD: prefix.h,v 1.2 2001/03/29 04:08:21 mickey Exp $       */
+
+/*
+ *  (c) Copyright 1985 HEWLETT-PACKARD COMPANY
+ *
+ *  To anyone who acknowledges that this file is provided "AS IS"
+ *  without any express or implied warranty:
+ *      permission to use, copy, modify, and distribute this file
+ *  for any purpose is hereby granted without fee, provided that
+ *  the above copyright notice and this notice appears in all
+ *  copies, and that the name of Hewlett-Packard Company not be
+ *  used in advertising or publicity pertaining to distribution
+ *  of the software without specific, written prior permission.
+ *  Hewlett-Packard Company makes no representations about the
+ *  suitability of this software for any purpose.
+ */
+
+/*
+ * STANDARD INCLUDE FILE FOR MILLICODE
+ * Every source file must include this file.
+ *
+ * Hardware General Registers
+ *
+ * Frame Offsets (millicode convention!)
+ * Used when calling other millicode routines.
+ * Stack unwinding is dependent upon these definitions.
+ * r31_slot    .equ    -20
+ * sr0_slot    .equ    -16
+ */
+
+#include <machine/asm.h>
+
+#define DEFINE(name, value)name:       .EQU    value
+#ifdef milliext
+#ifdef PIC
+#define MILLI_BE(lbl) \
+  BL    .+8,r1\
+  ! ADDIL L%lbl-labl/**/lbl,r1\
+  ! .LABEL labl/**/lbl\
+  ! BE    R%lbl-labl/**/lbl(sr7,r1)
+
+#define MILLI_BEN(lbl) \
+  BL    .+8,r1\
+  ! ADDIL L%lbl-labl/**/lbl,r1\
+  ! .LABEL labl/**/lbl\
+  ! BE,N  R%lbl-labl/**/lbl(sr7,r1)
+
+#define MILLI_BLE(lbl) \
+  BL    .+8,r1\
+  ! ADDIL L%lbl-labl/**/lbl,r1\
+  ! .LABEL labl/**/lbl \
+  ! BLE   R%lbl-labl/**/lbl(sr7,r1)
+
+#define MILLI_BLEN(lbl) \
+  BL    .+8,r1\
+  ! ADDIL L%lbl-labl/**/lbl,r1\
+  ! .LABEL labl/**/lbl\
+  ! BLE,N R%lbl-labl/**/lbl(sr7,r1)
+#else
+#define MILLI_BE(lbl)   BE    lbl(sr7,r0)
+#define MILLI_BEN(lbl)  BE,n  lbl(sr7,r0)
+#define MILLI_BLE(lbl) BLE   lbl(sr7,r0)
+#define MILLI_BLEN(lbl)        BLE,n lbl(sr7,r0)
+#endif
+
+#define MILLIRETN      BE,n  0(sr0,r31)
+#define MILLIRET       BE    0(sr0,r31)
+#define MILLI_RETN     BE,n  0(sr0,r31)
+#define MILLI_RET      BE    0(sr0,r31)
+
+#else
+#define MILLI_BE(lbl)  B     lbl
+#define MILLI_BEN(lbl)  B,n   lbl
+#define MILLI_BLE(lbl) BL    lbl,r31
+#define MILLI_BLEN(lbl)        BL,n  lbl,r31
+#define MILLIRETN      BV,n  0(r31)
+#define MILLIRET       BV    0(r31)
+#define MILLI_RETN     BV,n  0(r31)
+#define MILLI_RET      BV    0(r31)
+#endif
+; VERSION is used wherever ".version" can appear in a routine
+;#define VERSION .version
+#define VERSION ;
diff --git a/sys/lib/libkern/arch/hppa/spcopy.S b/sys/lib/libkern/arch/hppa/spcopy.S
new file mode 100644 (file)
index 0000000..da462b9
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: spcopy.S,v 1.1 2002/06/06 20:03:39 fredette Exp $      */
+
+#define SPCOPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/i386/Makefile.inc b/sys/lib/libkern/arch/i386/Makefile.inc
new file mode 100644 (file)
index 0000000..e0c4596
--- /dev/null
@@ -0,0 +1,11 @@
+#      $NetBSD: Makefile.inc,v 1.31 2009/08/14 19:23:53 dsl Exp $
+
+SRCS+= byte_swap_2.S byte_swap_4.S ffs.S
+SRCS+= memchr.S memcmp.S memcpy.S memmove.S memset.S
+SRCS+= random.S
+SRCS+= strcat.S strchr.S strcmp.S
+SRCS+= strcpy.S strlen.S
+SRCS+= strrchr.S
+SRCS+= scanc.S skpc.S
+
+SRCS+= crc32.c
diff --git a/sys/lib/libkern/arch/i386/random.S b/sys/lib/libkern/arch/i386/random.S
new file mode 100644 (file)
index 0000000..9670ff1
--- /dev/null
@@ -0,0 +1,96 @@
+/*     $NetBSD: random.S,v 1.6 2010/09/07 20:35:50 pooka Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+#include <machine/asm.h>
+
+       .data
+randseed:
+       .long   1
+       .text
+ENTRY(random)
+       movl    $16807,%eax
+       PIC_PROLOGUE
+       imull   PIC_GOTOFF(randseed)
+       PIC_EPILOGUE
+       shld    $1,%eax,%edx
+       andl    $0x7fffffff,%eax
+       addl    %edx,%eax
+       js      neg
+       PIC_PROLOGUE
+       movl    %eax,PIC_GOTOFF(randseed)
+       PIC_EPILOGUE
+       ret
+neg:
+       subl    $0x7fffffff,%eax
+       PIC_PROLOGUE
+       movl    %eax,PIC_GOTOFF(randseed)
+       PIC_EPILOGUE
+       ret
diff --git a/sys/lib/libkern/arch/i386/scanc.S b/sys/lib/libkern/arch/i386/scanc.S
new file mode 100644 (file)
index 0000000..6f77e83
--- /dev/null
@@ -0,0 +1,56 @@
+/*     $NetBSD: scanc.S,v 1.9 2008/04/28 20:24:06 martin Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(scanc)
+       movl    4(%esp),%ecx
+       testl   %ecx,%ecx
+       jz      3f
+       pushl   %esi
+       pushl   %edi
+       movl    16(%esp),%esi
+       movl    20(%esp),%edi
+       movb    24(%esp),%dl
+       xorl    %eax,%eax
+       cld
+1:
+       lodsb
+       testb   %dl,(%eax,%edi)
+       jnz     2f
+       decl    %ecx
+       jnz     1b
+2:
+       popl    %edi
+       popl    %esi
+3:
+       movl    %ecx,%eax
+       ret
diff --git a/sys/lib/libkern/arch/i386/skpc.S b/sys/lib/libkern/arch/i386/skpc.S
new file mode 100644 (file)
index 0000000..fddb7b3
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $NetBSD: skpc.S,v 1.6 2008/04/28 20:24:06 martin Exp $  */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(skpc)
+       pushl   %edi
+       movl    16(%esp),%edi
+       movl    12(%esp),%ecx
+       movl    8(%esp),%eax
+       cld
+       repe
+       scasb
+       je      1f
+       incl    %ecx
+1:
+       movl    %ecx,%eax
+       popl    %edi
+       ret
diff --git a/sys/lib/libkern/arch/ia64/Makefile.inc b/sys/lib/libkern/arch/ia64/Makefile.inc
new file mode 100644 (file)
index 0000000..c55b01e
--- /dev/null
@@ -0,0 +1,8 @@
+#      $NetBSD: Makefile.inc,v 1.4 2009/08/14 19:23:54 dsl Exp $
+#
+
+SRCS+= ffs.c
+
+SRCS+= divdi3.S divsi3.S modsi3.S moddi3.S udivdi3.S udivsi3.S
+SRCS+= umoddi3.S umodsi3.S bswap64.S bswap32.S bswap16.S ntohl.S htonl.S
+SRCS+= memcpy.S
diff --git a/sys/lib/libkern/arch/ia64/bswap16.S b/sys/lib/libkern/arch/ia64/bswap16.S
new file mode 100644 (file)
index 0000000..95f0dfe
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: bswap16.S,v 1.2 2006/04/07 14:27:33 cherry Exp $       */
+       
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ *     from: NetBSD: htons.S,v 1.1 1996/04/17 22:36:54 cgd
+ *     from: src/sys/libkern/ia64/htons.S,v 1.2 2002/02/18 20:35:21
+ *
+ * $FreeBSD$
+ */
+
+#define        NAME    bswap16
+
+#include "byte_swap_2.S"
diff --git a/sys/lib/libkern/arch/ia64/bswap32.S b/sys/lib/libkern/arch/ia64/bswap32.S
new file mode 100644 (file)
index 0000000..7cf66de
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: bswap32.S,v 1.2 2006/04/07 14:27:33 cherry Exp $       */
+       
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ *     from: NetBSD: htonl.S,v 1.1 1996/04/17 22:36:52 cgd
+ *     from: src/sys/libkern/ia64/htonl.S,v 1.2 2002/02/18 20:35:21
+ *
+ * $FreeBSD$
+ */
+
+#define        NAME    bswap32
+
+#include "byte_swap_4.S"
diff --git a/sys/lib/libkern/arch/ia64/bswap64.S b/sys/lib/libkern/arch/ia64/bswap64.S
new file mode 100644 (file)
index 0000000..1214379
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: bswap64.S,v 1.1 2009/07/20 11:23:04 kiyohara Exp $     */
+       
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ *     from: NetBSD: htonl.S,v 1.1 1996/04/17 22:36:52 cgd
+ *     from: src/sys/libkern/ia64/htonl.S,v 1.2 2002/02/18 20:35:21
+ *
+ * $FreeBSD$
+ */
+
+#define        NAME    bswap64
+
+#include "byte_swap_8.S"
diff --git a/sys/lib/libkern/arch/ia64/byte_swap_2.S b/sys/lib/libkern/arch/ia64/byte_swap_2.S
new file mode 100644 (file)
index 0000000..975bc9c
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: byte_swap_2.S,v 1.2 2006/04/07 14:27:33 cherry Exp $   */
+
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+
+#ifndef NAME
+#error NAME not defined
+#endif
+
+/*
+ * Byte-swap a 2-byte quantity.  (Convert 0x0123 to 0x2301.)
+ *
+ * Argument is an unsigned 2-byte integer (u_int16_t).
+ */
+ENTRY(NAME, 1)
+       mux1    r16=in0,@rev
+       ;;
+       extr.u  r8=r16,48,16
+       br.ret.sptk.few rp
+END(NAME)
diff --git a/sys/lib/libkern/arch/ia64/byte_swap_4.S b/sys/lib/libkern/arch/ia64/byte_swap_4.S
new file mode 100644 (file)
index 0000000..a600aa4
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: byte_swap_4.S,v 1.2 2006/04/07 14:27:33 cherry Exp $   */
+
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+
+#ifndef NAME
+#error NAME not defined
+#endif
+
+/*
+ * Byte-swap a 4-byte quantity.  (Convert 0x01234567 to 0x67452301.)
+ *
+ * Argument is an unsigned 4-byte integer (u_int32_t).
+ */
+ENTRY(NAME, 1)
+       mux1    r16=in0,@rev
+       ;;
+       extr.u  r8=r16,32,32
+       br.ret.sptk.few rp
+END(NAME)
diff --git a/sys/lib/libkern/arch/ia64/byte_swap_8.S b/sys/lib/libkern/arch/ia64/byte_swap_8.S
new file mode 100644 (file)
index 0000000..aee6784
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: byte_swap_8.S,v 1.1 2009/07/20 11:23:04 kiyohara Exp $ */
+
+/*-
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+
+#ifndef NAME
+#error NAME not defined
+#endif
+
+/*
+ * Byte-swap a 8-byte quantity.
+ *   (Convert 0x0123456789012345 to 0x4523018967452301.)
+ *
+ * Argument is an unsigned 8-byte integer (u_int64_t).
+ */
+ENTRY(NAME, 1)
+       mux1    r8=in0,@rev
+       br.ret.sptk.few rp
+END(NAME)
diff --git a/sys/lib/libkern/arch/ia64/divdi3.S b/sys/lib/libkern/arch/ia64/divdi3.S
new file mode 100644 (file)
index 0000000..9c51828
--- /dev/null
@@ -0,0 +1,142 @@
+.file "__divdi3.s"
+
+// $NetBSD: divdi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+.proc __divdi3#
+.align 32
+.global __divdi3#
+.align 32
+
+// 64-bit signed integer divide
+
+__divdi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mmi
+
+  // 64-BIT SIGNED INTEGER DIVIDE BEGINS HERE
+
+  setf.sig f8=r32
+  setf.sig f9=r33
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  fcvt.xf f6=f8
+  nop.b 0
+} { .mfb
+  nop.m 0
+  fcvt.xf f7=f9
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  // Step (11)
+  // q = trunc (q3)
+  fcvt.fx.trunc.s1 f8=f8
+  nop.b 0;;
+} { .mmi
+  // quotient will be in r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 64-BIT SIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __divdi3
diff --git a/sys/lib/libkern/arch/ia64/divsi3.S b/sys/lib/libkern/arch/ia64/divsi3.S
new file mode 100644 (file)
index 0000000..7cb55d0
--- /dev/null
@@ -0,0 +1,124 @@
+.file "__divsi3.s"
+
+// $NetBSD: divsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit signed integer divide
+
+.proc __divsi3#
+.align 32
+.global __divsi3#
+.align 32
+
+__divsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT SIGNED INTEGER DIVIDE BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit signed integer dividend
+  //    r33 - 32-bit signed integer divisor
+  //    r8 - 32-bit signed integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9
+  // predicate registers used: p6
+
+  sxt4 r32=r32
+  sxt4 r33=r33;;
+} { .mmb
+  setf.sig f6=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  fcvt.xf f6=f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f6=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f7=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f6=f7,f6,f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f7=f7,f7,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f7,f6,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fx.trunc.s1 f8=f8
+  nop.i 0;;
+} { .mmi
+  // quotient will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT SIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __divsi3
diff --git a/sys/lib/libkern/arch/ia64/htonl.S b/sys/lib/libkern/arch/ia64/htonl.S
new file mode 100644 (file)
index 0000000..3bae41f
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: htonl.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    htonl
+
+#include "byte_swap_4.S"
diff --git a/sys/lib/libkern/arch/ia64/memcpy.S b/sys/lib/libkern/arch/ia64/memcpy.S
new file mode 100644 (file)
index 0000000..67c83ce
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: memcpy.S,v 1.1 2006/04/07 13:57:43 cherry Exp $        */
+       
+#include <machine/asm.h>
+
diff --git a/sys/lib/libkern/arch/ia64/moddi3.S b/sys/lib/libkern/arch/ia64/moddi3.S
new file mode 100644 (file)
index 0000000..32ad0a2
--- /dev/null
@@ -0,0 +1,159 @@
+.file "__moddi3.s"
+
+// $NetBSD: moddi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 64-bit signed integer remainder
+
+.proc __moddi3#
+.align 32
+.global __moddi3#
+.align 32
+
+__moddi3:
+
+{ .mii
+  alloc r31=ar.pfs,3,0,0,0
+  nop.i 0
+  nop.i 0
+} { .mmb
+
+  // 64-BIT SIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 64-bit signed integer dividend, called a below
+  //    r33 - 64-bit signed integer divisor, called b below
+  //    r8 - 64-bit signed integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9, f10, f11, f12
+  // predicate registers used: p6
+
+  setf.sig f12=r32  // holds a in integer form
+  setf.sig f7=r33
+  nop.b 0
+} { .mlx
+  nop.m 0
+  //movl r2=0x8000000000000000;;
+  movl r2=0xffffffffffffffff;;
+} { .mfi
+  // get the 2's complement of b
+  sub r33=r0,r33
+  fcvt.xf f6=f12
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xf f7=f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  setf.sig f7=r33
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (11) q = trunc(q3)
+  fcvt.fx.trunc.s1 f8=f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (12) r = a + (-b) * q
+  xma.l f8=f8,f7,f12
+  nop.i 0;;
+}  { .mib
+  getf.sig r8=f8
+  nop.i 0
+  nop.b 0
+} 
+
+  // 64-BIT SIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mib
+  nop.m 0
+  nop.i 0
+  br.ret.sptk b0;;
+}
+
+.endp __moddi3
diff --git a/sys/lib/libkern/arch/ia64/modsi3.S b/sys/lib/libkern/arch/ia64/modsi3.S
new file mode 100644 (file)
index 0000000..1fa6d64
--- /dev/null
@@ -0,0 +1,131 @@
+.file "__modsi3.s"
+
+// $NetBSD: modsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit signed integer remainder
+
+.proc __modsi3#
+.align 32
+.global __modsi3#
+.align 32
+
+__modsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT SIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit signed integer dividend
+  //    r33 - 32-bit signed integer divisor
+  //    r8 - 32-bit signed integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9, f10, f11
+  // predicate registers used: p6
+
+  sxt4 r32=r32
+  sxt4 r33=r33;;
+} { .mmb
+  setf.sig f11=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  // get 2's complement of b
+  sub r33=r0,r33
+  fcvt.xf f6=f11
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f8=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  // 2's complement of b
+  setf.sig f7=r33
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f10=f8,f10,f10
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f8=f8,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f8,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fx.trunc.s1 f8=f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (8) r = a + (-b) * q
+  xma.l f8=f8,f7,f11
+  nop.i 0;;
+}  { .mmi
+  // remainder will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT SIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __modsi3
diff --git a/sys/lib/libkern/arch/ia64/ntohl.S b/sys/lib/libkern/arch/ia64/ntohl.S
new file mode 100644 (file)
index 0000000..257fb16
--- /dev/null
@@ -0,0 +1,32 @@
+/*     $NetBSD: ntohl.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#define        NAME    ntohl
+
+#include "byte_swap_4.S"
diff --git a/sys/lib/libkern/arch/ia64/udivdi3.S b/sys/lib/libkern/arch/ia64/udivdi3.S
new file mode 100644 (file)
index 0000000..7cb9f6e
--- /dev/null
@@ -0,0 +1,143 @@
+.file "__udivdi3.s"
+
+// $NetBSD: udivdi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+.proc __udivdi3#
+.align 32
+.global __udivdi3#
+.align 32
+
+// 64-bit unsigned integer divide
+
+__udivdi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+}
+
+{ .mmi
+
+  // 64-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+  setf.sig f8=r32
+  setf.sig f9=r33
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  fma.s1 f6=f8,f1,f0
+  nop.b 0
+} { .mfb
+  nop.m 0
+  fma.s1 f7=f9,f1,f0
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfb
+  nop.m 0
+  // (11) q = trunc(q3)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.b 0;;
+} { .mmi
+  // quotient will be in r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 64-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __udivdi3
diff --git a/sys/lib/libkern/arch/ia64/udivsi3.S b/sys/lib/libkern/arch/ia64/udivsi3.S
new file mode 100644 (file)
index 0000000..51b1f14
--- /dev/null
@@ -0,0 +1,124 @@
+.file "__udivsi3.s"
+
+// $NetBSD: udivsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit unsigned integer divide
+
+.proc __udivsi3#
+.align 32
+.global __udivsi3#
+.align 32
+
+__udivsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit unsigned integer dividend
+  //    r33 - 32-bit unsigned integer divisor
+  //    r8 - 32-bit unsigned integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9
+  // predicate registers used: p6
+
+  zxt4 r32=r32
+  zxt4 r33=r33;;
+} { .mmb
+  setf.sig f6=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  fcvt.xf f6=f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f6=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f7=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f6=f7,f6,f6
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f7=f7,f7,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f7,f6,f6
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+} { .mmi
+  // quotient will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __udivsi3
diff --git a/sys/lib/libkern/arch/ia64/umoddi3.S b/sys/lib/libkern/arch/ia64/umoddi3.S
new file mode 100644 (file)
index 0000000..38e539d
--- /dev/null
@@ -0,0 +1,155 @@
+.file "__umoddi3.s"
+
+// $NetBSD: umoddi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+  // 64-bit unsigned integer remainder
+
+.proc __umoddi3#
+.align 32
+.global __umoddi3#
+.align 32
+
+__umoddi3:
+
+{ .mii
+  alloc r31=ar.pfs,3,0,0,0
+  nop.i 0
+  nop.i 0
+} { .mmb
+
+  // 64-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 64-bit unsigned integer dividend, called a below
+  //    r33 - 64-bit unsigned integer divisor, called b below
+  //    r8 - 64-bit unsigned integer result
+  // floating-point registers used: f6, f7, f8, f9, f10, f11, f12
+  // predicate registers used: p6
+
+  setf.sig f12=r32  // holds a in integer form
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  // get 2's complement of b
+  sub r33=r0,r33
+  fcvt.xuf.s1 f6=f12
+  nop.i 0
+} { .mfi
+  nop.m 0
+  fcvt.xuf.s1 f7=f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (1)
+  // y0 = 1 / b in f8
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (2)
+  // q0 = a * y0 in f10
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (3)
+  // e0 = 1 - b * y0 in f9
+  (p6) fnma.s1 f9=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (4)
+  // q1 = q0 + e0 * q0 in f10
+  (p6) fma.s1 f10=f9,f10,f10
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // Step (5)
+  // e1 = e0 * e0 in f11
+  (p6) fma.s1 f11=f9,f9,f0
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (6)
+  // y1 = y0 + e0 * y0 in f8
+  (p6) fma.s1 f8=f9,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (7)
+  // q2 = q1 + e1 * q1 in f9
+  (p6) fma.s1 f9=f11,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (8)
+  // y2 = y1 + e1 * y1 in f8
+  (p6) fma.s1 f8=f11,f8,f8
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // Step (9)
+  // r2 = a - b * q2 in f10
+  (p6) fnma.s1 f10=f7,f9,f6
+  nop.i 0;;
+} { .mfi
+  // f7=-b
+  setf.sig f7=r33
+  // Step (10)
+  // q3 = q2 + r2 * y2 in f8
+  (p6) fma.s1 f8=f10,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (11) q = trunc(q3)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (12) r = a + (-b) * q
+  xma.l f8=f8,f7,f12
+  nop.i 0;;
+}  { .mib
+  getf.sig r8=f8
+  nop.i 0
+  nop.b 0
+}
+
+  // 64-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mib
+  nop.m 0
+  nop.i 0
+  br.ret.sptk b0;;
+}
+
+.endp __umoddi3
diff --git a/sys/lib/libkern/arch/ia64/umodsi3.S b/sys/lib/libkern/arch/ia64/umodsi3.S
new file mode 100644 (file)
index 0000000..ddac05d
--- /dev/null
@@ -0,0 +1,131 @@
+.file "__umodsi3.s"
+
+// $NetBSD: umodsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $
+
+//-
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, 
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, 
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS 
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+.section .text
+
+// 32-bit unsigned integer remainder
+
+.proc __umodsi3#
+.align 32
+.global __umodsi3#
+.align 32
+
+__umodsi3:
+
+{ .mii
+  alloc r31=ar.pfs,2,0,0,0
+  nop.i 0
+  nop.i 0;;
+} { .mii
+  nop.m 0
+
+  // 32-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+  // general register used:
+  //    r32 - 32-bit unsigned integer dividend
+  //    r33 - 32-bit unsigned integer divisor
+  //    r8 - 32-bit unsigned integer result
+  //    r2 - scratch register
+  // floating-point registers used: f6, f7, f8, f9, f10, f11
+  // predicate registers used: p6
+
+  zxt4 r32=r32
+  zxt4 r33=r33;;
+} { .mmb
+  setf.sig f11=r32
+  setf.sig f7=r33
+  nop.b 0;;
+} { .mfi
+  nop.m 0
+  fcvt.xf f6=f11
+  nop.i 0
+} { .mfi
+  // get 2's complement of b
+  sub r33=r0,r33
+  fcvt.xf f7=f7
+  mov r2 = 0x0ffdd;;
+} { .mfi
+  setf.exp f9 = r2
+  // (1) y0
+  frcpa.s1 f8,p6=f6,f7
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (2) q0 = a * y0
+  (p6) fma.s1 f10=f6,f8,f0
+  nop.i 0
+} { .mfi
+  nop.m 0
+  // (3) e0 = 1 - b * y0
+  (p6) fnma.s1 f8=f7,f8,f1
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (4) q1 = q0 + e0 * q0
+  (p6) fma.s1 f10=f8,f10,f10
+  nop.i 0
+} { .mfi
+  // get 2's complement of b
+  setf.sig f7=r33
+  // (5) e1 = e0 * e0 + 2^-34
+  (p6) fma.s1 f8=f8,f8,f9
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (6) q2 = q1 + e1 * q1
+  (p6) fma.s1 f8=f8,f10,f10
+  nop.i 0;;
+} { .mfi
+  nop.m 0
+  // (7) q = trunc(q2)
+  fcvt.fxu.trunc.s1 f8=f8
+  nop.i 0;;
+}  { .mfi
+  nop.m 0
+  // (8) r = a + (-b) * q
+  xma.l f8=f8,f7,f11
+  nop.i 0;;
+}  { .mmi
+  // remainder will be in the least significant 32 bits of r8 (if b != 0)
+  getf.sig r8=f8
+  nop.m 0
+  nop.i 0;;
+}
+
+  // 32-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mmb
+  nop.m 0
+  nop.m 0
+  br.ret.sptk b0;;
+}
+
+.endp __umodsi3
diff --git a/sys/lib/libkern/arch/m68k/DEFS.h b/sys/lib/libkern/arch/m68k/DEFS.h
new file mode 100644 (file)
index 0000000..f5c6689
--- /dev/null
@@ -0,0 +1,3 @@
+/*     $NetBSD: DEFS.h,v 1.4 1999/11/11 01:32:10 thorpej Exp $ */
+
+#include <machine/asm.h>
diff --git a/sys/lib/libkern/arch/m68k/Makefile.inc b/sys/lib/libkern/arch/m68k/Makefile.inc
new file mode 100644 (file)
index 0000000..4ab3b5f
--- /dev/null
@@ -0,0 +1,16 @@
+#      $NetBSD: Makefile.inc,v 1.30 2009/08/14 19:23:54 dsl Exp $
+
+SRCS+= bswap16.S bswap32.S bswap64.S
+SRCS+= memcmp.S memcpy.S memmove.S memset.S
+SRCS+= strcat.S strchr.S strcmp.S
+SRCS+= strcpy.S strlen.S strncmp.S strncpy.S strrchr.S
+SRCS+= scanc.S skpc.S
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
+SRCS+= ffs.S
+
+.if defined(MACHINE_ARCH) && (${MACHINE_ARCH} == "m68000")
+SRCS+= mulsi3.S divsi3.S udivsi3.S modsi3.S umodsi3.S
+random.o random.d: random.c
+.else
+SRCS+= random.S
+.endif
diff --git a/sys/lib/libkern/arch/m68k/random.S b/sys/lib/libkern/arch/m68k/random.S
new file mode 100644 (file)
index 0000000..96fc68a
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: random.S,v 1.4 2009/01/06 01:24:56 pooka Exp $ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+#include <machine/asm.h>
+
+       .data
+ASLOCAL(randseed)
+       .long   1
+
+ENTRY(random)
+       movl    #16807, %d0
+#ifdef PIC
+       lea     %pc@(_GLOBAL_OFFSET_TABLE_@GOTPC), %a0
+       movl    _ASM_LABEL(randseed)@GOT(%a0), %d2
+       mulsl   (%d2), %d1:%d0
+#else
+       mulsl   _ASM_LABEL(randseed), %d1:%d0
+#endif
+       lsll    #1, %d0
+       roxll   #2, %d1
+       addl    %d1, %d0
+       moveql  #1, %d1
+       addxl   %d1, %d0
+       lsrl    #1, %d0
+#ifdef PIC
+       movl    %d0, (%d2)
+#else
+       movl    %d0, _ASM_LABEL(randseed)
+#endif
+       rts
diff --git a/sys/lib/libkern/arch/m68k/scanc.S b/sys/lib/libkern/arch/m68k/scanc.S
new file mode 100644 (file)
index 0000000..5ca5dce
--- /dev/null
@@ -0,0 +1,63 @@
+/*     $NetBSD: scanc.S,v 1.6 2011/02/08 20:20:27 rmind Exp $  */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: Utah Hdr: locore.s 1.58 91/04/22
+ *     @(#)locore.s    7.11 (Berkeley) 5/9/91
+ */
+
+#include "DEFS.h"
+
+/*
+ * Emulate fancy VAX string operations:
+ *     scanc(count, startc, table, mask)
+ */
+ENTRY(scanc)
+       movl    %sp@(4),%d0     | get length
+       jeq     Lscdone         | nothing to do, return
+       movl    %sp@(8),%a0     | start of scan
+       movl    %sp@(12),%a1    | table to compare with
+       movb    %sp@(19),%d1    | and mask to use
+       movw    %d2,%sp@-       | need a scratch register
+       clrw    %d2             | clear it out
+       subqw   #1,%d0          | adjust for dbra
+Lscloop:
+       movb    %a0@+,%d2       | get character
+       movb    %a1@(0,%d2:w),%d2 | get table entry
+       andb    %d1,%d2         | mask it
+       dbne    %d0,Lscloop     | keep going til no more or non-zero
+       addqw   #1,%d0          | overshot by one
+       movw    %sp@+,%d2       | restore scratch
+Lscdone:
+       rts
diff --git a/sys/lib/libkern/arch/m68k/skpc.S b/sys/lib/libkern/arch/m68k/skpc.S
new file mode 100644 (file)
index 0000000..7a73a46
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: skpc.S,v 1.6 2011/02/08 20:20:27 rmind Exp $   */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: Utah Hdr: locore.s 1.58 91/04/22
+ *     @(#)locore.s    7.11 (Berkeley) 5/9/91
+ */
+
+#include "DEFS.h"
+
+/*
+ * Emulate fancy VAX string operations:
+ *     skpc(mask, count, startc)
+ */
+ENTRY(skpc)
+       movl    %sp@(8),%d0     | get length
+       jeq     Lskdone         | nothing to do, return
+       movb    %sp@(7),%d1     | mask to use
+       movl    %sp@(12),%a0    | where to start
+       subqw   #1,%d0          | adjust for dbcc
+Lskloop:
+       cmpb    %a0@+,%d1       | compate with mask
+       dbne    %d0,Lskloop     | keep going til no more or zero
+       addqw   #1,%d0          | overshot by one
+Lskdone:
+       rts
diff --git a/sys/lib/libkern/arch/mips/Makefile.inc b/sys/lib/libkern/arch/mips/Makefile.inc
new file mode 100644 (file)
index 0000000..740ff22
--- /dev/null
@@ -0,0 +1,14 @@
+#      $NetBSD: Makefile.inc,v 1.23 2010/01/20 18:13:40 pgoyette Exp $
+#
+#      There are likely more that we will notice when we go native
+
+NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c
+NO_SRCS+= __main.c
+
+SRCS+= memchr.c memcmp.c random.c scanc.c \
+       skpc.c strcat.c strcpy.c strcasecmp.c \
+       strncasecmp.c strncmp.c strncpy.c strtoul.c
+
+SRCS+= byte_swap_2.S byte_swap_4.S byte_swap_8.S \
+       ffs.S memcpy.S memset2.c memmove.S \
+       strlen.S strcmp.S
diff --git a/sys/lib/libkern/arch/powerpc/Makefile.inc b/sys/lib/libkern/arch/powerpc/Makefile.inc
new file mode 100644 (file)
index 0000000..661af33
--- /dev/null
@@ -0,0 +1,15 @@
+#      $NetBSD: Makefile.inc,v 1.31 2011/07/02 03:35:03 matt Exp $
+
+SRCS+= bswap16.c bswap32.c
+SRCS+= htonl.c htons.c ntohl.c ntohs.c
+SRCS+= syncicache.c
+
+SRCS+= ffs.S memset.S strlen.S
+SRCS+= gprsavrest.S
+
+# Disable the asm versions on evbppc because they break the Explora
+.if ${MACHINE} == "evbppc"
+memcpy.o: memcpy.c
+memcmp.o: memcmp.c
+memmove.o: memmove.c
+.endif
diff --git a/sys/lib/libkern/arch/powerpc/gprsavrest.S b/sys/lib/libkern/arch/powerpc/gprsavrest.S
new file mode 100644 (file)
index 0000000..739325e
--- /dev/null
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <powerpc/asm.h>
+
+__RCSID("$NetBSD: gprsavrest.S,v 1.4 2011/10/28 02:00:50 christos Exp $")
+
+#ifndef RESTGPR
+# define RESTGPR(n)    RESTOREXGPR(_restgpr_,n,_x)
+# define RESTGPR_END(n)        RESTOREXGPR_END(_restgpr_,n,_x)
+# define SAVEGPR(n)    SAVEXGPR(_savegpr_,n,)
+# define SAVEGPR_END(n)        SAVEXGPR_END(_savegpr_,n,)
+#endif
+
+#define RESTOREXGPR(a,n,b) \
+       .hidden a##n##b; ENTRY_NOPROFILE(a##n##b); lwz  n,(-4*(32-n))(11)
+#define SAVEXGPR(a,n,b) \
+       .hidden a##n##b; ENTRY_NOPROFILE(a##n##b); stw  n,(-4*(32-n))(11)
+#ifdef _LP64
+# define SAVEXGPR_END(a,n,b) 
+# define RESTOREXGPR_END(a,n,b) 
+#else
+# define SAVEXGPR_END(a,n,b) \
+       .size a##n##b,.-a##n##b
+# define RESTOREXGPR_END(a,n,b) \
+       .size a##n##b,.-a##n##b
+#endif
+
+       RESTGPR(14)
+       RESTGPR(15)
+       RESTGPR(16)
+       RESTGPR(17)
+       RESTGPR(18)
+       RESTGPR(19)
+       RESTGPR(20)
+       RESTGPR(21)
+       RESTGPR(22)
+       RESTGPR(23)
+       RESTGPR(24)
+       RESTGPR(25)
+       RESTGPR(26)
+       RESTGPR(27)
+       RESTGPR(28)
+       RESTGPR(29)
+       RESTGPR(30)
+       RESTGPR(31)
+       lwz     0,4(11)
+       mtlr    0
+       mr      1,11
+       blr
+       RESTGPR_END(14)
+       RESTGPR_END(15)
+       RESTGPR_END(16)
+       RESTGPR_END(17)
+       RESTGPR_END(18)
+       RESTGPR_END(19)
+       RESTGPR_END(20)
+       RESTGPR_END(21)
+       RESTGPR_END(22)
+       RESTGPR_END(23)
+       RESTGPR_END(24)
+       RESTGPR_END(25)
+       RESTGPR_END(26)
+       RESTGPR_END(27)
+       RESTGPR_END(28)
+       RESTGPR_END(29)
+       RESTGPR_END(30)
+       RESTGPR_END(31)
+
+       SAVEGPR(14)
+       SAVEGPR(15)
+       SAVEGPR(16)
+       SAVEGPR(17)
+       SAVEGPR(18)
+       SAVEGPR(19)
+       SAVEGPR(20)
+       SAVEGPR(21)
+       SAVEGPR(22)
+       SAVEGPR(23)
+       SAVEGPR(24)
+       SAVEGPR(25)
+       SAVEGPR(26)
+       SAVEGPR(27)
+       SAVEGPR(28)
+       SAVEGPR(29)
+       SAVEGPR(30)
+       SAVEGPR(31)
+       blr
+       SAVEGPR_END(14)
+       SAVEGPR_END(15)
+       SAVEGPR_END(16)
+       SAVEGPR_END(17)
+       SAVEGPR_END(18)
+       SAVEGPR_END(19)
+       SAVEGPR_END(20)
+       SAVEGPR_END(21)
+       SAVEGPR_END(22)
+       SAVEGPR_END(23)
+       SAVEGPR_END(24)
+       SAVEGPR_END(25)
+       SAVEGPR_END(26)
+       SAVEGPR_END(27)
+       SAVEGPR_END(28)
+       SAVEGPR_END(29)
+       SAVEGPR_END(30)
+       SAVEGPR_END(31)
diff --git a/sys/lib/libkern/arch/powerpc/memset.S b/sys/lib/libkern/arch/powerpc/memset.S
new file mode 100644 (file)
index 0000000..d6f8a83
--- /dev/null
@@ -0,0 +1,99 @@
+/*     $NetBSD: memset.S,v 1.7 2011/01/17 07:07:36 matt Exp $ */
+
+/*-
+ * Copyright (C) 2003  Matt Thomas <matt@3am-software.com>
+ * Copyright (C) 2001  Martin J. Laubach <mjl@NetBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*----------------------------------------------------------------------*/
+
+#include <machine/asm.h>
+
+/*----------------------------------------------------------------------*/
+/*
+     void bzero(void *b r3, size_t len r4);
+     void *memset(void *b r3, int c r4, size_t len r5);
+*/
+/*----------------------------------------------------------------------*/
+
+#define r_dst  %r4
+#define r_len  %r5
+#define r_tmp  %r6
+#define r_val  %r0
+
+ENTRY(bzero)
+               li      r_val, 0                /* Value to fill with */
+               mr      r_len, %r4
+               b       cb_memset
+
+ENTRY(memset)
+               mr      r_val, %r4              /* Value to fill with */
+
+cb_memset:
+               cmplwi  r_len, 0                /* is the length 0? */
+               beqlr-                          /*    nothing to do */
+               mr      r_dst, %r3
+               /*
+                * r3=start, r4=dstptr, r5=length, r0=fill-val
+                */
+               cmplwi  r_len, 6                /* more than 6 bytes? */
+               bgt     complex_fill            /*    do it the complex way */
+               subi    r_dst, r_dst, 1         /* presubtract for stbu */
+simple_fill:   mtctr   r_len                   /* set CTR */
+1:             stbu    r_val, 1(r_dst)         /* update memory */
+               bdnz+   1b                      /*    until CTR is 0 */
+               blr                             /* return */
+
+complex_fill:
+               rlwimi  r_val, r_val, 8, 16, 23 /* word extend fill value */
+               rlwimi  r_val, r_val, 16, 0, 15
+               andi.   r_tmp, r_dst, 0x03
+               beq+    word_fill               /* already aligned to word? */
+               andi.   r_tmp, r_dst, 0x01
+               beq     half_fill               /* aligned to halfword? */
+               stb     r_val, 0(r_dst)
+               addi    r_dst, r_dst, 1
+               subi    r_len, r_len, 1         /* subtract byte */
+               andi.   r_tmp, r_dst, 0x02
+               beq     word_fill               /* aligned to word? */
+half_fill:
+               sth     r_val, 0(r_dst)
+               addi    r_dst, r_dst, 2
+               subi    r_len, r_len, 2         /* subtract halfword */
+
+word_fill:
+               cmplwi  r_len, 4                /* we have more than 4 bytes? */
+               blt-    trailing_bytes          /* no?  finish writing */
+               srwi    r_tmp, r_len, 2         /* get word count */
+               mtctr   r_tmp
+               subi    r_dst, r_dst, 4
+1:             stwu    r_val, 4(r_dst)
+               bdnz+   1b
+
+trailing_bytes:
+               andi.   r_len, r_len, 0x03      /* how much left? */
+               beqlr+                          /* nothing? return */
+               addi    r_dst, r_dst, 3
+               b       simple_fill
diff --git a/sys/lib/libkern/arch/powerpc/syncicache.c b/sys/lib/libkern/arch/powerpc/syncicache.c
new file mode 100644 (file)
index 0000000..e364666
--- /dev/null
@@ -0,0 +1,132 @@
+/*     $NetBSD: syncicache.c,v 1.14 2008/03/18 20:11:43 he Exp $       */
+
+/*
+ * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank.
+ * Copyright (C) 1995-1997, 1999 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/param.h>
+#if    defined(_KERNEL)
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <uvm/uvm_extern.h>
+#endif
+#if    !defined(_STANDALONE)
+#include <sys/sysctl.h>
+#endif
+
+#include <machine/cpu.h>
+
+
+#if defined(_STANDALONE)
+#ifndef        CACHELINESIZE
+#error "Must know the size of a cache line"
+#endif
+static struct cache_info _cache_info = {
+       CACHELINESIZE,
+       CACHELINESIZE,
+       CACHELINESIZE,
+       CACHELINESIZE
+};
+#define CACHEINFO      _cache_info
+#elif defined(_KERNEL)
+#define        CACHEINFO       (curcpu()->ci_ci)
+#else
+static void getcachelinesize (void);
+
+static int _cachelinesize = 0;
+
+static struct cache_info _cache_info;
+#define CACHEINFO      _cache_info
+
+static void
+getcachelinesize(void)
+{
+       static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
+       static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO };
+       size_t clen = sizeof(_cache_info);
+
+       if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]),
+               &_cache_info, &clen, NULL, 0) == 0) {
+               _cachelinesize = _cache_info.dcache_line_size;
+               return;
+       }
+
+       /* Try older deprecated sysctl */
+       clen = sizeof(_cachelinesize);
+       if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
+                  &_cachelinesize, &clen, NULL, 0) < 0
+           || !_cachelinesize)
+               abort();
+
+       _cache_info.dcache_size = _cachelinesize;
+       _cache_info.dcache_line_size = _cachelinesize;
+       _cache_info.icache_size = _cachelinesize;
+       _cache_info.icache_line_size = _cachelinesize;
+       /* If there is no cache, indicate we have issued the sysctl. */
+       if (!_cachelinesize)
+               _cachelinesize = 1;
+}
+#endif
+
+void
+__syncicache(void *from, size_t len)
+{
+       size_t l, off;
+       size_t linesz;
+       char *p;
+
+#if    !defined(_KERNEL) && !defined(_STANDALONE)
+       if (!_cachelinesize)
+               getcachelinesize();
+#endif
+
+       if (CACHEINFO.dcache_size > 0) {
+               linesz = CACHEINFO.dcache_line_size;
+               off = (uintptr_t)from & (linesz - 1);
+               l = (len + off + linesz - 1) & ~(linesz - 1);
+               p = (char *)from - off;
+               do {
+                       __asm volatile ("dcbst 0,%0" :: "r"(p));
+                       p += linesz;
+               } while ((l -= linesz) != 0);
+       }
+       __asm volatile ("sync");
+
+       if (CACHEINFO.icache_size > 0 ) {
+               linesz = CACHEINFO.icache_line_size;
+               off = (uintptr_t)from & (linesz - 1);
+               l = (len + off + linesz - 1) & ~(linesz - 1);
+               p = (char *)from - off;
+               do {
+                       __asm volatile ("icbi 0,%0" :: "r"(p));
+                       p += linesz;
+               } while ((l -= linesz) != 0);
+       }
+       __asm volatile ("sync; isync");
+}
diff --git a/sys/lib/libkern/arch/sh3/Makefile.inc b/sys/lib/libkern/arch/sh3/Makefile.inc
new file mode 100644 (file)
index 0000000..19a2fa5
--- /dev/null
@@ -0,0 +1,12 @@
+#      $NetBSD: Makefile.inc,v 1.19 2011/08/04 03:20:09 uwe Exp $
+
+SRCS+= ffs.S
+SRCS+= memset.S
+SRCS+= memmove.S memcpy.S byte_swap_2.S byte_swap_4.S byte_swap_8.S
+SRCS+= ashiftrt.S ashlsi3.S ashrsi3.S lshrsi3.S movstr.S movstr_i4.S
+SRCS+= movstrSI.S movstrSI12_i4.S mulsi3.S sdivsi3.S udivsi3.S
+
+# newer gcc uses different integer division millicode by default
+SRCS+=  sdivsi3_i4i.S udivsi3_i4i.S
+
+NO_SRCS+= bswap64.c
diff --git a/sys/lib/libkern/arch/sh3/ashiftrt.S b/sys/lib/libkern/arch/sh3/ashiftrt.S
new file mode 100644 (file)
index 0000000..ed5b09e
--- /dev/null
@@ -0,0 +1,180 @@
+/*     $NetBSD: ashiftrt.S,v 1.7 2009/01/07 22:15:18 uwe Exp $ */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __ashiftrt_r4_0
+       .hidden __ashiftrt_r4_1
+       .hidden __ashiftrt_r4_2
+       .hidden __ashiftrt_r4_3
+       .hidden __ashiftrt_r4_4
+       .hidden __ashiftrt_r4_5
+       .hidden __ashiftrt_r4_6
+       .hidden __ashiftrt_r4_7
+       .hidden __ashiftrt_r4_8
+       .hidden __ashiftrt_r4_9
+       .hidden __ashiftrt_r4_10
+       .hidden __ashiftrt_r4_11
+       .hidden __ashiftrt_r4_12
+       .hidden __ashiftrt_r4_13
+       .hidden __ashiftrt_r4_14
+       .hidden __ashiftrt_r4_15
+       .hidden __ashiftrt_r4_16
+       .hidden __ashiftrt_r4_17
+       .hidden __ashiftrt_r4_18
+       .hidden __ashiftrt_r4_19
+       .hidden __ashiftrt_r4_20
+       .hidden __ashiftrt_r4_21
+       .hidden __ashiftrt_r4_22
+       .hidden __ashiftrt_r4_23
+       .hidden __ashiftrt_r4_24
+       .hidden __ashiftrt_r4_25
+       .hidden __ashiftrt_r4_26
+       .hidden __ashiftrt_r4_27
+       .hidden __ashiftrt_r4_28
+       .hidden __ashiftrt_r4_29
+       .hidden __ashiftrt_r4_30
+       .hidden __ashiftrt_r4_31
+#endif  /* __ELF__ */
+
+
+NENTRY(__ashiftrt_r4_31)
+       shll    r4
+       rts
+        subc   r4, r4
+
+ALTENTRY(__ashiftrt_r4_30)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_29)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_28)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_27)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_26)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_25)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_24)
+       shlr16  r4
+       shlr8   r4
+       rts
+        exts.b r4, r4
+
+ALTENTRY(__ashiftrt_r4_23)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_22)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_21)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_20)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_19)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_18)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_17)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_16)
+       shlr16  r4
+       rts
+        exts.w r4, r4
+
+ALTENTRY(__ashiftrt_r4_15)
+       swap.w  r4, r4
+       cmp/pz  r4
+       bf/s    1f
+        exts.w r4, r4
+       rts
+        shll   r4
+1:
+       sett
+       rts
+        rotcl  r4
+
+ALTENTRY(__ashiftrt_r4_14)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_13)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_12)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_11)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_10)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_9)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_8)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_7)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_6)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_5)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_4)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_3)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_2)
+       shar    r4
+
+ALTENTRY(__ashiftrt_r4_1)
+       rts
+        shar   r4
+
+ALTENTRY(__ashiftrt_r4_0)
+       rts
+        nop
diff --git a/sys/lib/libkern/arch/sh3/ashlsi3.S b/sys/lib/libkern/arch/sh3/ashlsi3.S
new file mode 100644 (file)
index 0000000..ea36b88
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: ashlsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $  */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __ashlsi3
+#endif
+
+
+NENTRY(__ashlsi3)
+       shld    r5, r4
+       rts
+        mov    r4, r0
diff --git a/sys/lib/libkern/arch/sh3/ashrsi3.S b/sys/lib/libkern/arch/sh3/ashrsi3.S
new file mode 100644 (file)
index 0000000..3da686a
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: ashrsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $  */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __ashrsi3
+#endif
+
+
+NENTRY(__ashrsi3)
+       tst     r5, r5
+       bt      noshift
+
+       neg     r5, r5
+       shad    r5, r4
+       rts
+        mov    r4, r0
+
+noshift:
+       rts
+        mov    r4, r0
diff --git a/sys/lib/libkern/arch/sh3/byte_swap_2.S b/sys/lib/libkern/arch/sh3/byte_swap_2.S
new file mode 100644 (file)
index 0000000..5feede0
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: byte_swap_2.S,v 1.6 2006/04/14 09:23:01 nonaka Exp $   */
+
+/*-
+ * Copyright (C) 1999 SHIMIZU Ryo.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+#undef _LOCORE
+#define        _LOCORE         /* XXX not really, just assembly-code source */
+#include <machine/endian.h>
+
+ENTRY(bswap16)
+#if BYTE_ORDER == LITTLE_ENDIAN
+ALTENTRY(ntohs)
+ALTENTRY(htons)
+#endif
+       extu.w  r4, r4
+       rts
+        swap.b r4, r0
+
+#if BYTE_ORDER == BIG_ENDIAN
+ENTRY(ntohs)
+ALTENTRY(htons)
+       rts
+        extu.w r4, r0
+#endif
diff --git a/sys/lib/libkern/arch/sh3/byte_swap_4.S b/sys/lib/libkern/arch/sh3/byte_swap_4.S
new file mode 100644 (file)
index 0000000..c875483
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $NetBSD: byte_swap_4.S,v 1.5 2006/04/14 09:23:01 nonaka Exp $   */
+
+/*-
+ * Copyright (C) 1999 SHIMIZU Ryo.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+#undef _LOCORE
+#define        _LOCORE         /* XXX not really, just assembly-code source */
+#include <machine/endian.h>
+
+ENTRY(bswap32)
+#if BYTE_ORDER == LITTLE_ENDIAN
+ALTENTRY(ntohl)
+ALTENTRY(htonl)
+#endif
+       swap.b  r4,r0
+       swap.w  r0,r0
+       rts
+        swap.b r0,r0
+
+#if BYTE_ORDER == BIG_ENDIAN
+ENTRY(ntohl)
+ALTENTRY(htonl)
+       rts
+        mov    r4, r0
+#endif
diff --git a/sys/lib/libkern/arch/sh3/byte_swap_8.S b/sys/lib/libkern/arch/sh3/byte_swap_8.S
new file mode 100644 (file)
index 0000000..5714b63
--- /dev/null
@@ -0,0 +1,43 @@
+/*     $NetBSD: byte_swap_8.S,v 1.2 2005/12/11 12:24:44 christos Exp $ */
+
+/*
+ * Copyright (c) 2003 Valeriy E. Ushakov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+       RCSID("$NetBSD: byte_swap_8.S,v 1.2 2005/12/11 12:24:44 christos Exp $")
+#endif
+
+ENTRY(bswap64)
+       swap.b  r4,r4
+       swap.b  r5,r5
+       swap.w  r4,r4
+       swap.w  r5,r5
+       swap.b  r4,r1
+       rts
+        swap.b r5,r0
diff --git a/sys/lib/libkern/arch/sh3/lshrsi3.S b/sys/lib/libkern/arch/sh3/lshrsi3.S
new file mode 100644 (file)
index 0000000..42c0cab
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: lshrsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $  */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __lshrsi3
+#endif
+
+
+NENTRY(__lshrsi3)
+       tst     r5, r5
+       bt      noshift
+
+       neg     r5, r5
+       shld    r5, r4
+       rts
+        mov    r4, r0
+
+noshift:
+       rts
+        mov    r4, r0
diff --git a/sys/lib/libkern/arch/sh3/movstr.S b/sys/lib/libkern/arch/sh3/movstr.S
new file mode 100644 (file)
index 0000000..7786b23
--- /dev/null
@@ -0,0 +1,99 @@
+/*     $NetBSD: movstr.S,v 1.9 2009/01/07 22:15:18 uwe Exp $   */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __movstr, __movmem
+#endif
+
+
+NENTRY(__movstr)
+       mov     #16, r0
+       cmp/gt  r0, r6
+       bf      loop2
+
+       .align  2
+loop1:
+       mov.l   @r5+, r0
+       mov.l   r0, @r4
+       mov.l   @r5+, r0
+       mov.l   r0, @(4, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(8, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(12, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(16, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(20, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(24, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(28, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(32, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(36, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(40, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(44, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(48, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(52, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(56, r4)
+       mov.l   @r5+, r0
+       mov.l   r0, @(60, r4)
+       add     #-16, r6
+       add     #64, r4
+
+       mov     #16, r0
+       cmp/gt  r0, r6
+       bt      loop1
+
+loop2:
+       add     #-32, r6
+       .align  2
+1:
+       mov.l   @r5+, r0
+       mov.l   r0, @r4
+       add     #4, r4
+       add     #1, r6
+       tst     r6, r6
+       bf      1b
+
+       rts
+        nop
+
+
+/* gcc4 uses movmem, older versions use movstr */
+STRONG_ALIAS(__movmem, __movstr)
diff --git a/sys/lib/libkern/arch/sh3/movstrSI.S b/sys/lib/libkern/arch/sh3/movstrSI.S
new file mode 100644 (file)
index 0000000..75b4104
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $NetBSD: movstrSI.S,v 1.8 2009/01/07 22:15:18 uwe Exp $ */
+
+/*
+ * Copyright (c) 2000 SHIMIZU Ryo.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __movstrSI4, __movmemSI4 
+       .hidden __movstrSI8, __movmemSI8 
+       .hidden __movstrSI12, __movmemSI12
+       .hidden __movstrSI16, __movmemSI16
+       .hidden __movstrSI20, __movmemSI20
+       .hidden __movstrSI24, __movmemSI24
+       .hidden __movstrSI28, __movmemSI28
+       .hidden __movstrSI32, __movmemSI32
+       .hidden __movstrSI36, __movmemSI36
+       .hidden __movstrSI40, __movmemSI40
+       .hidden __movstrSI44, __movmemSI44
+       .hidden __movstrSI48, __movmemSI48
+       .hidden __movstrSI52, __movmemSI52
+       .hidden __movstrSI56, __movmemSI56
+       .hidden __movstrSI60, __movmemSI60
+       .hidden __movstrSI64, __movmemSI64
+#endif
+
+
+NENTRY(__movstrSI64)
+       mov.l   @(60, r5), r0
+       mov.l   r0, @(60, r4)
+ALTENTRY(__movstrSI60)
+       mov.l   @(56, r5), r0
+       mov.l   r0, @(56, r4)
+ALTENTRY(__movstrSI56)
+       mov.l   @(52, r5), r0
+       mov.l   r0, @(52, r4)
+ALTENTRY(__movstrSI52)
+       mov.l   @(48, r5), r0
+       mov.l   r0, @(48, r4)
+ALTENTRY(__movstrSI48)
+       mov.l   @(44, r5), r0
+       mov.l   r0, @(44, r4)
+ALTENTRY(__movstrSI44)
+       mov.l   @(40, r5), r0
+       mov.l   r0, @(40, r4)
+ALTENTRY(__movstrSI40)
+       mov.l   @(36, r5), r0
+       mov.l   r0, @(36, r4)
+ALTENTRY(__movstrSI36)
+       mov.l   @(32, r5), r0
+       mov.l   r0, @(32, r4)
+ALTENTRY(__movstrSI32)
+       mov.l   @(28, r5), r0
+       mov.l   r0, @(28, r4)
+ALTENTRY(__movstrSI28)
+       mov.l   @(24, r5), r0
+       mov.l   r0, @(24, r4)
+ALTENTRY(__movstrSI24)
+       mov.l   @(20, r5), r0
+       mov.l   r0, @(20, r4)
+ALTENTRY(__movstrSI20)
+       mov.l   @(16, r5), r0
+       mov.l   r0, @(16, r4)
+ALTENTRY(__movstrSI16)
+       mov.l   @(12, r5), r0
+       mov.l   r0, @(12, r4)
+ALTENTRY(__movstrSI12)
+       mov.l   @(8, r5), r0
+       mov.l   r0, @(8, r4)
+ALTENTRY(__movstrSI8)
+       mov.l   @(4, r5), r0
+       mov.l   r0, @(4, r4)
+ALTENTRY(__movstrSI4)
+       mov.l   @r5, r0
+       rts
+        mov.l  r0, @r4
+
+
+/* gcc4 uses movmem, older versions use movstr */
+STRONG_ALIAS(__movmemSI4, __movstrSI4)
+STRONG_ALIAS(__movmemSI8, __movstrSI8)
+STRONG_ALIAS(__movmemSI12, __movstrSI12)
+STRONG_ALIAS(__movmemSI16, __movstrSI16)
+STRONG_ALIAS(__movmemSI20, __movstrSI20)
+STRONG_ALIAS(__movmemSI24, __movstrSI24)
+STRONG_ALIAS(__movmemSI28, __movstrSI28)
+STRONG_ALIAS(__movmemSI32, __movstrSI32)
+STRONG_ALIAS(__movmemSI36, __movstrSI36)
+STRONG_ALIAS(__movmemSI40, __movstrSI40)
+STRONG_ALIAS(__movmemSI44, __movstrSI44)
+STRONG_ALIAS(__movmemSI48, __movstrSI48)
+STRONG_ALIAS(__movmemSI52, __movstrSI52)
+STRONG_ALIAS(__movmemSI56, __movstrSI56)
+STRONG_ALIAS(__movmemSI60, __movstrSI60)
+STRONG_ALIAS(__movmemSI64, __movstrSI64)
diff --git a/sys/lib/libkern/arch/sh3/movstrSI12_i4.S b/sys/lib/libkern/arch/sh3/movstrSI12_i4.S
new file mode 100644 (file)
index 0000000..2ef09c4
--- /dev/null
@@ -0,0 +1,21 @@
+/*     $NetBSD: movstrSI12_i4.S,v 1.2 2009/01/07 22:15:18 uwe Exp $    */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __movstrSI12_i4, __movmemSI12_i4
+#endif
+
+
+NENTRY(__movstrSI12_i4)
+       mov.l   @r5, r0
+       mov.l   @(4, r5), r1
+       mov.l   @(8, r5), r2
+       mov.l   r0, @r4
+       mov.l   r1, @(4, r4)
+       rts
+        mov.l  r2, @(8, r4)
+
+/* gcc4 uses movmem, older versions use movstr */
+STRONG_ALIAS(__movmemSI12_i4, __movstrSI12_i4)
diff --git a/sys/lib/libkern/arch/sh3/movstr_i4.S b/sys/lib/libkern/arch/sh3/movstr_i4.S
new file mode 100644 (file)
index 0000000..24c47e3
--- /dev/null
@@ -0,0 +1,80 @@
+/*     $NetBSD: movstr_i4.S,v 1.6 2009/01/07 22:15:18 uwe Exp $        */
+
+/*-
+ * Copyright (C) 2002 SHIMIZU Ryo.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __movstr_i4_odd, __movmem_i4_odd
+       .hidden __movstr_i4_even, __movmem_i4_even
+#endif
+
+
+NENTRY(__movstr_i4_odd)
+       add     #-8,r4
+       nop
+odd_loop:
+       mov.l   @r5+,r0
+       add     #8,r4
+       mov.l   @r5+,r1
+       dt      r6
+       mov.l   r0,@(0,r4)
+       bf/s    odd_loop
+        mov.l  r1,@(4,r4)
+
+       mov.l   @r5+,r0
+       mov.l   @r5+,r1
+       mov.l   @r5+,r2
+       mov.l   r0,@(8,r4)
+       mov.l   r1,@(12,r4)
+       rts
+        mov.l  r2,@(16,r4)
+
+
+NENTRY(__movstr_i4_even)
+       add     #-8,r4
+       nop
+even_loop:
+       mov.l   @r5+,r0
+       add     #8,r4
+       mov.l   @r5+,r1
+       dt      r6
+       mov.l   r0,@(0,r4)
+       bf/s    even_loop
+        mov.l  r1,@(4,r4)
+
+       mov.l   @r5+,r0
+       mov.l   @r5+,r1
+       mov.l   r0,@(8,r4)
+       rts
+        mov.l  r1,@(12,r4)
+
+
+/* gcc4 uses movmem, older versions use movstr */
+STRONG_ALIAS(__movmem_i4_odd, __movstr_i4_odd)
+STRONG_ALIAS(__movmem_i4_even, __movstr_i4_even)
diff --git a/sys/lib/libkern/arch/sh3/mulsi3.S b/sys/lib/libkern/arch/sh3/mulsi3.S
new file mode 100644 (file)
index 0000000..9f6e9c0
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: mulsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $   */
+
+/*-
+ * Copyright (C) 1999 Tsubai Masanari.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+
+#ifdef __ELF__
+       .hidden __mulsi3
+#endif
+
+
+NENTRY(__mulsi3)
+       mul.l   r4, r5
+       rts
+        sts    macl, r0
diff --git a/sys/lib/libkern/arch/sh3/sdivsi3.S b/sys/lib/libkern/arch/sh3/sdivsi3.S
new file mode 100644 (file)
index 0000000..e9723c9
--- /dev/null
@@ -0,0 +1,92 @@
+/*     $NetBSD: sdivsi3.S,v 1.12 2011/08/05 01:59:39 uwe Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)udivsi3.s     5.1 (Berkeley) 5/15/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+       RCSID("$NetBSD: sdivsi3.S,v 1.12 2011/08/05 01:59:39 uwe Exp $")
+#endif
+
+/*
+ * IMPOTANT: This function is special.
+ *
+ * This function is an auxiliary "millicode" function that is
+ * referenced by the code generated by gcc for signed integer
+ * division.  But gcc does NOT treat a call to this function as an
+ * ordinary function call - it can clobber only R1, R2 and R3.
+ *
+ * See the definition of "divsi3_i1" in gcc/config/sh/sh.md
+ *
+ * As the consequence this function cannot be called via any
+ * indirection that assumes normal calling convention:
+ *
+ * . cannot have _PROF_PROLOGUE
+ * . cannot be called via PLT (not relevant for kernel)
+ */
+
+
+#ifdef __ELF__
+       .hidden __sdivsi3
+#endif
+
+
+/* r0 <= r4 / r5 */
+NENTRY(__sdivsi3)
+       mov     r4, r0
+       mov     r5, r1
+
+       tst     r1, r1
+       bt      .L_div_by_zero
+
+       mov     #0, r2
+       div0s   r2, r0
+       subc    r3, r3
+       subc    r2, r0
+       div0s   r1, r3
+#define DIVSTEP        rotcl r0; div1 r1, r3
+       /* repeat 32 times */
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+#undef DIVSTEP
+       rotcl   r0
+
+       rts
+        addc   r2, r0
+
+.L_div_by_zero:
+       rts
+        mov    #0, r0
diff --git a/sys/lib/libkern/arch/sh3/sdivsi3_i4i.S b/sys/lib/libkern/arch/sh3/sdivsi3_i4i.S
new file mode 100644 (file)
index 0000000..3ea32e1
--- /dev/null
@@ -0,0 +1,108 @@
+/*     $NetBSD: sdivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $      */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)udivsi3.s     5.1 (Berkeley) 5/15/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+       RCSID("$NetBSD: sdivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $")
+#endif
+
+/*
+ * IMPOTANT: This function is special.
+ *
+ * This function is an auxiliary "millicode" function that is
+ * referenced by the code generated by gcc for signed integer
+ * division.  But gcc does NOT treat a call to this function as an
+ * ordinary function call - it can clobber only R1, MACL and MACH.
+ *
+ * See the definition of "divsi3_i4_int" in gcc/config/sh/sh.md
+ *
+ * As the consequence this function cannot be called via any
+ * indirection that assumes normal calling convention:
+ *
+ * . cannot have _PROF_PROLOGUE
+ * . cannot be called via PLT (not relevant for kernel)
+ *
+ * XXX: uwe: Older gcc used __sdivsi3; newer uses __sdivsi3_i4i - a
+ * heavily tuned version that is NOT compatible with __sdivsi3 because
+ * it clobbers different registers.  We don't want to link the kernel
+ * against libgcc and we don't have resources to write heavily tuned
+ * version ourselves, so clone __sdivsi3 but adjust the code to
+ * conform to the __sdivsi3_i4i clobber spec.
+ */
+
+
+#ifdef __ELF__
+       .hidden __sdivsi3_i4i
+#endif
+
+
+/* r0 <= r4 / r5 */
+NENTRY(__sdivsi3_i4i)
+       mov     r4, r0
+       mov     r5, r1
+
+       tst     r1, r1
+       bt      .L_div_by_zero
+
+       !! this version cannot clobber r2 and r3, but can clobber macl/mach
+       lds     r2, macl
+       lds     r3, mach
+
+       mov     #0, r2
+       div0s   r2, r0
+       subc    r3, r3
+       subc    r2, r0
+       div0s   r1, r3
+#define DIVSTEP        rotcl r0; div1 r1, r3
+       /* repeat 32 times */
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+#undef DIVSTEP
+       rotcl   r0
+
+       addc    r2, r0
+
+       sts     mach, r3
+       sts     macl, r2
+
+       rts
+        nop
+
+.L_div_by_zero:
+       rts
+        mov    #0, r0
diff --git a/sys/lib/libkern/arch/sh3/udivsi3.S b/sys/lib/libkern/arch/sh3/udivsi3.S
new file mode 100644 (file)
index 0000000..18a65e5
--- /dev/null
@@ -0,0 +1,86 @@
+/*     $NetBSD: udivsi3.S,v 1.11 2011/08/05 01:59:39 uwe Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)udivsi3.s     5.1 (Berkeley) 5/15/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+       RCSID("$NetBSD: udivsi3.S,v 1.11 2011/08/05 01:59:39 uwe Exp $")
+#endif
+
+/*
+ * IMPOTANT: This function is special.
+ *
+ * This function is an auxiliary "millicode" function that is
+ * referenced by the code generated by gcc for unsigned integer
+ * division.  But gcc does NOT treat a call to this function as an
+ * ordinary function call - it can clobber only R4.
+ *
+ * See the definition of "udivsi3_i1" in gcc/config/sh/sh.md
+ *
+ * As the consequence this function cannot be called via any
+ * indirection that assumes normal calling convention:
+ *
+ * . cannot have _PROF_PROLOGUE
+ * . cannot be called via PLT (not relevant for kernel)
+ */
+
+
+#ifdef __ELF__
+       .hidden __udivsi3
+#endif
+
+
+/* r0 <= r4 / r5 */
+NENTRY(__udivsi3)
+       tst     r5, r5
+       bt      .L_div_by_zero
+
+       mov     #0, r0
+       div0u
+#define DIVSTEP        rotcl r4; div1 r5, r0
+       /* repeat 32 times */
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+#undef DIVSTEP
+       rotcl   r4
+
+       rts
+        mov    r4, r0
+
+.L_div_by_zero:
+       rts
+        mov    #0, r0
diff --git a/sys/lib/libkern/arch/sh3/udivsi3_i4i.S b/sys/lib/libkern/arch/sh3/udivsi3_i4i.S
new file mode 100644 (file)
index 0000000..0e9cb6e
--- /dev/null
@@ -0,0 +1,94 @@
+/*     $NetBSD: udivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $      */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     from: @(#)udivsi3.s     5.1 (Berkeley) 5/15/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+       RCSID("$NetBSD: udivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $")
+#endif
+
+/*
+ * IMPOTANT: This function is special.
+ *
+ * This function is an auxiliary "millicode" function that is
+ * referenced by the code generated by gcc for unsigned integer
+ * division.  But gcc does NOT treat a call to this function as an
+ * ordinary function call - it can clobber only R1, MACL and MACH.
+ *
+ * See the definition of "udivsi3_i4_int" in gcc/config/sh/sh.md
+ *
+ * As the consequence this function cannot be called via any
+ * indirection that assumes normal calling convention:
+ *
+ * . cannot have _PROF_PROLOGUE
+ * . cannot be called via PLT (not relevant for kernel)
+ *
+ * XXX: uwe: Older gcc used __udivsi3; newer uses __udivsi3_i4i - a
+ * heavily tuned version that is NOT compatible with __udivsi3 because
+ * it clobbers different registers.  We don't want to link the kernel
+ * against libgcc and we don't have resources to write heavily tuned
+ * version ourselves, so clone __udivsi3 but adjust the code to
+ * conform to the __udivsi3_i4i clobber spec.
+ */
+
+
+#ifdef __ELF__
+       .hidden __udivsi3_i4i
+#endif
+
+
+/* r0 <= r4 / r5 */
+NENTRY(__udivsi3_i4i)
+       tst     r5, r5
+       bt      .L_div_by_zero
+
+       mov     r4, r1          ! cannot clobber r4 in this version
+       mov     #0, r0
+       div0u
+#define DIVSTEP        rotcl r1; div1 r5, r0
+       /* repeat 32 times */
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+       DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP;
+#undef DIVSTEP
+       rotcl   r1
+
+       rts
+        mov    r1, r0
+
+.L_div_by_zero:
+       rts
+        mov    #0, r0
diff --git a/sys/lib/libkern/arch/sparc/Makefile.inc b/sys/lib/libkern/arch/sparc/Makefile.inc
new file mode 100644 (file)
index 0000000..c31bdb7
--- /dev/null
@@ -0,0 +1,40 @@
+#      $NetBSD: Makefile.inc,v 1.34 2009/08/14 19:23:54 dsl Exp $
+
+SRCS+= ffs.S
+SRCS+= memset.S
+SRCS+= strlen.S
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
+SRCS+= random.S
+
+SRCS+= bswap16.c bswap32.c
+
+SRCS+= mul.S umul.S saveregs.S
+
+# `source' files built from m4 source
+# the name `div.o' is taken for the ANSI C `div' function, hence sdiv here
+SRCS+= rem.S sdiv.S udiv.S urem.S
+CLEANFILES+=rem.S sdiv.S udiv.S urem.S
+
+.SUFFIXES: .m4
+
+.PATH.m4: ${KERNDIR}/arch/${MACHINE_ARCH}
+
+sdiv.S: divrem.m4
+       echo 'building ${.TARGET} from ${.ALLSRC}'
+       (echo "define(NAME,\`.div')define(OP,\`div')define(S,\`true')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+udiv.S: divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`.udiv')define(OP,\`div')define(S,\`false')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+rem.S: divrem.m4
+       echo 'building ${.TARGET} from ${.ALLSRC}'
+       (echo "define(NAME,\`.rem')define(OP,\`rem')define(S,\`true')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+urem.S: divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`.urem')define(OP,\`rem')define(S,\`false')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
diff --git a/sys/lib/libkern/arch/sparc/divrem.m4 b/sys/lib/libkern/arch/sparc/divrem.m4
new file mode 100644 (file)
index 0000000..26b5fa5
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp
+ * $NetBSD: divrem.m4,v 1.9 2011/06/13 03:23:53 mrg Exp $
+ */
+
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+       .asciz "@(#)divrem.m4   8.1 (Berkeley) 6/4/93"
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  NAME       name of function to generate
+ *  OP         OP=div => %o0 / %o1; OP=rem => %o0 % %o1
+ *  S          S=true => signed; S=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N          how many bits per iteration we try to get (4)
+ *  WORDSIZE   total number of bits (32)
+ *
+ * Derived constants:
+ *  TWOSUPN    2^N, for label generation (m4 exponentiation currently broken)
+ *  TOPBITS    number of bits in the top `decade' of a number
+ *
+ * Important variables:
+ *  Q          the partial quotient under development (initially 0)
+ *  R          the remainder so far, initially the dividend
+ *  ITER       number of main division loop iterations required;
+ *             equal to ceil(log2(quotient) / N).  Note that this
+ *             is the log base (2^N) of the quotient.
+ *  V          the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *     ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+define(N, `4')
+define(TWOSUPN, `16')
+define(WORDSIZE, `32')
+define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N)))
+
+define(dividend, `%o0')
+define(divisor, `%o1')
+define(Q, `%o2')
+define(R, `%o3')
+define(ITER, `%o4')
+define(V, `%o5')
+
+/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */
+define(T, `%g1')
+define(SC, `%g5')
+ifelse(S, `true', `define(SIGN, `%g6')')
+
+/*
+ * This is the recursive definition for developing quotient digits.
+ *
+ * Parameters:
+ *  $1 the current depth, 1 <= $1 <= N
+ *  $2 the current accumulation of quotient bits
+ *  N  max depth
+ *
+ * We add a new bit to $2 and either recurse or insert the bits in
+ * the quotient.  R, Q, and V are inputs and outputs as defined above;
+ * the condition codes are expected to reflect the input R, and are
+ * modified to reflect the output R.
+ */
+define(DEVELOP_QUOTIENT_BITS,
+`      ! depth $1, accumulated bits $2
+       bl      L.$1.eval(TWOSUPN+$2)
+       srl     V,1,V
+       ! remainder is positive
+       subcc   R,V,R
+       ifelse($1, N,
+       `       b       9f
+               add     Q, ($2*2+1), Q
+       ', `    DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')')
+L.$1.eval(TWOSUPN+$2):
+       ! remainder is negative
+       addcc   R,V,R
+       ifelse($1, N,
+       `       b       9f
+               add     Q, ($2*2-1), Q
+       ', `    DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')')
+       ifelse($1, 1, `9:')')
+
+#include <machine/asm.h>
+#include <machine/trap.h>
+
+FUNC(NAME)
+ifelse(S, `true',
+`      ! compute sign of result; if neither is negative, no problem
+       orcc    divisor, dividend, %g0  ! either negative?
+       bge     2f                      ! no, go do the divide
+       ifelse(OP, `div',
+               `xor    divisor, dividend, SIGN',
+               `mov    dividend, SIGN')        ! compute sign in any case
+       tst     divisor
+       bge     1f
+       tst     dividend
+       ! divisor is definitely negative; dividend might also be negative
+       bge     2f                      ! if dividend not negative...
+       neg     divisor                 ! in any case, make divisor nonneg
+1:     ! dividend is negative, divisor is nonnegative
+       neg     dividend                ! make dividend nonnegative
+2:
+')
+       ! Ready to divide.  Compute size of quotient; scale comparand.
+       orcc    divisor, %g0, V
+       bnz     1f
+       mov     dividend, R
+
+               ! Divide by zero trap.  If it returns, return 0 (about as
+               ! wrong as possible, but that is what SunOS does...).
+               t       ST_DIV0
+               retl
+               clr     %o0
+
+1:
+       cmp     R, V                    ! if divisor exceeds dividend, done
+       blu     Lgot_result             ! (and algorithm fails otherwise)
+       clr     Q
+       sethi   %hi(1 << (WORDSIZE - TOPBITS - 1)), T
+       cmp     R, T
+       blu     Lnot_really_big
+       clr     ITER
+
+       ! `Here the dividend is >= 2^(31-N) or so.  We must be careful here,
+       ! as our usual N-at-a-shot divide step will cause overflow and havoc.
+       ! The number of bits in the result here is N*ITER+SC, where SC <= N.
+       ! Compute ITER in an unorthodox manner: know we need to shift V into
+       ! the top decade: so do not even bother to compare to R.'
+       1:
+               cmp     V, T
+               bgeu    3f
+               mov     1, SC
+               sll     V, N, V
+               b       1b
+               inc     ITER
+
+       ! Now compute SC.
+       2:      addcc   V, V, V
+               bcc     Lnot_too_big
+               inc     SC
+
+               ! We get here if the divisor overflowed while shifting.
+               ! This means that R has the high-order bit set.
+               ! Restore V and subtract from R.
+               sll     T, TOPBITS, T   ! high order bit
+               srl     V, 1, V         ! rest of V
+               add     V, T, V
+               b       Ldo_single_div
+               dec     SC
+
+       Lnot_too_big:
+       3:      cmp     V, R
+               blu     2b
+               nop
+               be      Ldo_single_div
+               nop
+       /* NB: these are commented out in the V8-Sparc manual as well */
+       /* (I do not understand this) */
+       ! V > R: went too far: back up 1 step
+       !       srl     V, 1, V
+       !       dec     SC
+       ! do single-bit divide steps
+       !
+       ! We have to be careful here.  We know that R >= V, so we can do the
+       ! first divide step without thinking.  BUT, the others are conditional,
+       ! and are only done if R >= 0.  Because both R and V may have the high-
+       ! order bit set in the first step, just falling into the regular
+       ! division loop will mess up the first time around.
+       ! So we unroll slightly...
+       Ldo_single_div:
+               deccc   SC
+               bl      Lend_regular_divide
+               nop
+               sub     R, V, R
+               mov     1, Q
+               b       Lend_single_divloop
+               nop
+       Lsingle_divloop:
+               sll     Q, 1, Q
+               bl      1f
+               srl     V, 1, V
+               ! R >= 0
+               sub     R, V, R
+               b       2f
+               inc     Q
+       1:      ! R < 0
+               add     R, V, R
+               dec     Q
+       2:
+       Lend_single_divloop:
+               deccc   SC
+               bge     Lsingle_divloop
+               tst     R
+               b,a     Lend_regular_divide
+
+Lnot_really_big:
+1:
+       sll     V, N, V
+       cmp     V, R
+       bleu    1b
+       inccc   ITER
+       be      Lgot_result
+       dec     ITER
+
+       tst     R       ! set up for initial iteration
+Ldivloop:
+       sll     Q, N, Q
+       DEVELOP_QUOTIENT_BITS(1, 0)
+Lend_regular_divide:
+       deccc   ITER
+       bge     Ldivloop
+       tst     R
+       bl,a    Lgot_result
+       ! non-restoring fixup here (one instruction only!)
+ifelse(OP, `div',
+`      dec     Q
+', `   add     R, divisor, R
+')
+
+Lgot_result:
+ifelse(S, `true',
+`      ! check to see if answer should be < 0
+       tst     SIGN
+       bl,a    1f
+       ifelse(OP, `div', `neg Q', `neg R')
+1:')
+       retl
+       ifelse(OP, `div', `mov Q, %o0', `mov R, %o0')
diff --git a/sys/lib/libkern/arch/sparc/random.S b/sys/lib/libkern/arch/sparc/random.S
new file mode 100644 (file)
index 0000000..d4d2bcc
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: random.S,v 1.3 2009/01/05 01:16:09 pooka Exp $ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+#include <machine/asm.h>
+
+       .data
+randseed:
+       .long   1
+
+       .text
+ENTRY(random)
+       sethi   %hi(16807), %o1
+       wr      %o1, %lo(16807), %y
+#ifdef PIC
+       PIC_PROLOGUE(%o5, %o2)
+       set     randseed, %g1
+       ld      [%o5 + %g1], %g1
+       ld      [%g1], %o0
+#else
+       sethi   %hi(randseed), %g1
+       ld      [%g1 + %lo(randseed)], %o0
+#endif
+       andcc   %g0, 0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %g0, %o2
+       rd      %y, %o3
+       srl     %o2, 16, %o1
+       set     0xffff, %o4
+       and     %o4, %o2, %o0
+       sll     %o0, 15, %o0
+       srl     %o3, 17, %o3
+       or      %o3, %o0, %o0
+       addcc   %o0, %o1, %o0
+       bneg    1f
+       sethi   %hi(0x7fffffff), %o1
+       retl
+#ifdef PIC
+       st      %o0, [%g1]
+#else
+       st      %o0, [%g1 + %lo(randseed)]
+#endif
+1:
+       or      %o1, %lo(0x7fffffff), %o1
+       add     %o0, 1, %o0
+       and     %o1, %o0, %o0
+       retl
+#ifdef PIC
+       st      %o0, [%g1]
+#else
+       st      %o0, [%g1 + %lo(randseed)]
+#endif
diff --git a/sys/lib/libkern/arch/sparc64/DEFS.h b/sys/lib/libkern/arch/sparc64/DEFS.h
new file mode 100644 (file)
index 0000000..c9686f3
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $NetBSD: DEFS.h,v 1.3 2005/12/11 12:24:45 christos Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)DEFS.h      8.1 (Berkeley) 6/4/93
+ */
+
+#include <machine/asm.h>
+
diff --git a/sys/lib/libkern/arch/sparc64/Makefile.inc b/sys/lib/libkern/arch/sparc64/Makefile.inc
new file mode 100644 (file)
index 0000000..42094cf
--- /dev/null
@@ -0,0 +1,36 @@
+#      $NetBSD: Makefile.inc,v 1.10 2009/08/14 19:23:55 dsl Exp $
+
+SRCS+= ffs.S
+SRCS+= strlen.S
+SRCS+= htonl.S htons.S ntohl.S ntohs.S
+SRCS+= random.S
+
+SRCS+= bswap16.c bswap32.c
+
+SRCS+= umul.S mul.S rem.S sdiv.S udiv.S umul.S urem.S
+SRCS+= mul.S saveregs.S umul.S
+
+# `source' files built from m4 source
+# the name `div.o' is taken for the ANSI C `div' function, hence sdiv here
+SRCS+= rem.S sdiv.S udiv.S urem.S
+CLEANFILES+=rem.S sdiv.S udiv.S urem.S
+
+sdiv.S: $M/divrem.m4
+       echo 'building ${.TARGET} from ${.ALLSRC}'
+       (echo "define(NAME,\`.div')define(OP,\`div')define(S,\`true')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+udiv.S: $M/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`.udiv')define(OP,\`div')define(S,\`false')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+rem.S: $M/divrem.m4
+       echo 'building ${.TARGET} from ${.ALLSRC}'
+       (echo "define(NAME,\`.rem')define(OP,\`rem')define(S,\`true')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
+
+urem.S: $M/divrem.m4
+       @echo 'building ${.TARGET} from ${.ALLSRC}'
+       @(echo "define(NAME,\`.urem')define(OP,\`rem')define(S,\`false')"; \
+        cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET}
diff --git a/sys/lib/libkern/arch/sparc64/divrem.m4 b/sys/lib/libkern/arch/sparc64/divrem.m4
new file mode 100644 (file)
index 0000000..03063ca
--- /dev/null
@@ -0,0 +1,273 @@
+/*     $NetBSD: divrem.m4,v 1.5 2005/12/11 12:24:45 christos Exp $     */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp
+ */
+
+#include <machine/asm.h>
+#include <machine/trap.h>
+
+/*
+ * Division and remainder, from Appendix E of the Sparc Version 8
+ * Architecture Manual, with fixes from Gordon Irlam.
+ */
+
+#if defined(LIBC_SCCS)
+       RCSID("$NetBSD: divrem.m4,v 1.5 2005/12/11 12:24:45 christos Exp $")
+#endif
+
+/*
+ * Input: dividend and divisor in %o0 and %o1 respectively.
+ *
+ * m4 parameters:
+ *  NAME       name of function to generate
+ *  OP         OP=div => %o0 / %o1; OP=rem => %o0 % %o1
+ *  S          S=true => signed; S=false => unsigned
+ *
+ * Algorithm parameters:
+ *  N          how many bits per iteration we try to get (4)
+ *  WORDSIZE   total number of bits (32)
+ *
+ * Derived constants:
+ *  TWOSUPN    2^N, for label generation (m4 exponentiation currently broken)
+ *  TOPBITS    number of bits in the top `decade' of a number
+ *
+ * Important variables:
+ *  Q          the partial quotient under development (initially 0)
+ *  R          the remainder so far, initially the dividend
+ *  ITER       number of main division loop iterations required;
+ *             equal to ceil(log2(quotient) / N).  Note that this
+ *             is the log base (2^N) of the quotient.
+ *  V          the current comparand, initially divisor*2^(ITER*N-1)
+ *
+ * Cost:
+ *  Current estimate for non-large dividend is
+ *     ceil(log2(quotient) / N) * (10 + 7N/2) + C
+ *  A large dividend is one greater than 2^(31-TOPBITS) and takes a
+ *  different path, as the upper bits of the quotient must be developed
+ *  one bit at a time.
+ */
+
+define(N, `4')
+define(TWOSUPN, `16')
+define(WORDSIZE, `32')
+define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N)))
+
+define(dividend, `%o0')
+define(divisor, `%o1')
+define(Q, `%o2')
+define(R, `%o3')
+define(ITER, `%o4')
+define(V, `%o5')
+
+/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */
+define(T, `%g1')
+define(SC, `%g5')
+ifelse(S, `true', `define(SIGN, `%g6')')
+
+/*
+ * This is the recursive definition for developing quotient digits.
+ *
+ * Parameters:
+ *  $1 the current depth, 1 <= $1 <= N
+ *  $2 the current accumulation of quotient bits
+ *  N  max depth
+ *
+ * We add a new bit to $2 and either recurse or insert the bits in
+ * the quotient.  R, Q, and V are inputs and outputs as defined above;
+ * the condition codes are expected to reflect the input R, and are
+ * modified to reflect the output R.
+ */
+define(DEVELOP_QUOTIENT_BITS,
+`      ! depth $1, accumulated bits $2
+       bl      L.$1.eval(TWOSUPN+$2)
+       srl     V,1,V
+       ! remainder is positive
+       subcc   R,V,R
+       ifelse($1, N,
+       `       b       9f
+               add     Q, ($2*2+1), Q
+       ', `    DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')')
+L.$1.eval(TWOSUPN+$2):
+       ! remainder is negative
+       addcc   R,V,R
+       ifelse($1, N,
+       `       b       9f
+               add     Q, ($2*2-1), Q
+       ', `    DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')')
+       ifelse($1, 1, `9:')')
+
+FUNC(NAME)
+ifelse(S, `true',
+`      ! compute sign of result; if neither is negative, no problem
+       orcc    divisor, dividend, %g0  ! either negative?
+       bge     2f                      ! no, go do the divide
+       ifelse(OP, `div',
+               `xor    divisor, dividend, SIGN',
+               `mov    dividend, SIGN')        ! compute sign in any case
+       tst     divisor
+       bge     1f
+       tst     dividend
+       ! divisor is definitely negative; dividend might also be negative
+       bge     2f                      ! if dividend not negative...
+       neg     divisor                 ! in any case, make divisor nonneg
+1:     ! dividend is negative, divisor is nonnegative
+       neg     dividend                ! make dividend nonnegative
+2:
+')
+       ! Ready to divide.  Compute size of quotient; scale comparand.
+       orcc    divisor, %g0, V
+       bnz     1f
+       mov     dividend, R
+
+               ! Divide by zero trap.  If it returns, return 0 (about as
+               ! wrong as possible, but that is what SunOS does...).
+               t       ST_DIV0
+               retl
+               clr     %o0
+
+1:
+       cmp     R, V                    ! if divisor exceeds dividend, done
+       blu     Lgot_result             ! (and algorithm fails otherwise)
+       clr     Q
+       sethi   %hi(1 << (WORDSIZE - TOPBITS - 1)), T
+       cmp     R, T
+       blu     Lnot_really_big
+       clr     ITER
+
+       ! `Here the dividend is >= 2^(31-N) or so.  We must be careful here,
+       ! as our usual N-at-a-shot divide step will cause overflow and havoc.
+       ! The number of bits in the result here is N*ITER+SC, where SC <= N.
+       ! Compute ITER in an unorthodox manner: know we need to shift V into
+       ! the top decade: so do not even bother to compare to R.'
+       1:
+               cmp     V, T
+               bgeu    3f
+               mov     1, SC
+               sll     V, N, V
+               b       1b
+               inc     ITER
+
+       ! Now compute SC.
+       2:      addcc   V, V, V
+               bcc     Lnot_too_big
+               inc     SC
+
+               ! We get here if the divisor overflowed while shifting.
+               ! This means that R has the high-order bit set.
+               ! Restore V and subtract from R.
+               sll     T, TOPBITS, T   ! high order bit
+               srl     V, 1, V         ! rest of V
+               add     V, T, V
+               b       Ldo_single_div
+               dec     SC
+
+       Lnot_too_big:
+       3:      cmp     V, R
+               blu     2b
+               nop
+               be      Ldo_single_div
+               nop
+       /* NB: these are commented out in the V8-Sparc manual as well */
+       /* (I do not understand this) */
+       ! V > R: went too far: back up 1 step
+       !       srl     V, 1, V
+       !       dec     SC
+       ! do single-bit divide steps
+       !
+       ! We have to be careful here.  We know that R >= V, so we can do the
+       ! first divide step without thinking.  BUT, the others are conditional,
+       ! and are only done if R >= 0.  Because both R and V may have the high-
+       ! order bit set in the first step, just falling into the regular
+       ! division loop will mess up the first time around.
+       ! So we unroll slightly...
+       Ldo_single_div:
+               deccc   SC
+               bl      Lend_regular_divide
+               nop
+               sub     R, V, R
+               mov     1, Q
+               b       Lend_single_divloop
+               nop
+       Lsingle_divloop:
+               sll     Q, 1, Q
+               bl      1f
+               srl     V, 1, V
+               ! R >= 0
+               sub     R, V, R
+               b       2f
+               inc     Q
+       1:      ! R < 0
+               add     R, V, R
+               dec     Q
+       2:
+       Lend_single_divloop:
+               deccc   SC
+               bge     Lsingle_divloop
+               tst     R
+               b,a     Lend_regular_divide
+
+Lnot_really_big:
+1:
+       sll     V, N, V
+       cmp     V, R
+       bleu    1b
+       inccc   ITER
+       be      Lgot_result
+       dec     ITER
+
+       tst     R       ! set up for initial iteration
+Ldivloop:
+       sll     Q, N, Q
+       DEVELOP_QUOTIENT_BITS(1, 0)
+Lend_regular_divide:
+       deccc   ITER
+       bge     Ldivloop
+       tst     R
+       bl,a    Lgot_result
+       ! non-restoring fixup here (one instruction only!)
+ifelse(OP, `div',
+`      dec     Q
+', `   add     R, divisor, R
+')
+
+Lgot_result:
+ifelse(S, `true',
+`      ! check to see if answer should be < 0
+       tst     SIGN
+       bl,a    1f
+       ifelse(OP, `div', `neg Q', `neg R')
+1:')
+       retl
+       ifelse(OP, `div', `mov Q, %o0', `mov R, %o0')
diff --git a/sys/lib/libkern/arch/sparc64/random.S b/sys/lib/libkern/arch/sparc64/random.S
new file mode 100644 (file)
index 0000000..86aeeb3
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: random.S,v 1.3 2009/01/05 01:16:09 pooka Exp $ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+#include <machine/asm.h>
+
+       .data
+randseed:
+       .long   1
+
+       .text
+ENTRY(random)
+       sethi   %hi(16807), %o1
+       wr      %o1, %lo(16807), %y
+#ifdef PIC
+       PIC_PROLOGUE(%o5, %o2)
+       set     randseed, %g1
+       ldx     [%o5 + %g1], %g1
+       ld      [%g1], %o0
+#else
+       sethi   %hi(randseed), %g1
+       ld      [%g1 + %lo(randseed)], %o0
+#endif
+       andcc   %g0, 0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %o0, %o2
+       mulscc  %o2, %g0, %o2
+       rd      %y, %o3
+       srl     %o2, 16, %o1
+       set     0xffff, %o4
+       and     %o4, %o2, %o0
+       sll     %o0, 15, %o0
+       srl     %o3, 17, %o3
+       or      %o3, %o0, %o0
+       addcc   %o0, %o1, %o0
+       bneg    1f
+       sethi   %hi(0x7fffffff), %o1
+       retl
+#ifdef PIC
+       st      %o0, [%g1]
+#else
+       st      %o0, [%g1 + %lo(randseed)]
+#endif
+1:
+       or      %o1, %lo(0x7fffffff), %o1
+       add     %o0, 1, %o0
+       and     %o1, %o0, %o0
+       retl
+#ifdef PIC
+       st      %o0, [%g1]
+#else
+       st      %o0, [%g1 + %lo(randseed)]
+#endif
diff --git a/sys/lib/libkern/arch/usermode/Makefile.inc b/sys/lib/libkern/arch/usermode/Makefile.inc
new file mode 100644 (file)
index 0000000..26c0316
--- /dev/null
@@ -0,0 +1,6 @@
+#      $NetBSD: Makefile.inc,v 1.3 2009/08/14 19:23:55 dsl Exp $
+#
+#      There are likely more that we will notice when we go native
+
+NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c
+NO_SRCS+= __main.c strlen.c strcmp.c
diff --git a/sys/lib/libkern/arch/vax/Makefile.inc b/sys/lib/libkern/arch/vax/Makefile.inc
new file mode 100644 (file)
index 0000000..18e9abc
--- /dev/null
@@ -0,0 +1,11 @@
+#      $NetBSD: Makefile.inc,v 1.24 2010/03/15 11:46:49 uwe Exp $
+#
+#      The rest of the lib routines are in machine/macros.h
+#
+
+SRCS+= blkcpy.S blkset.S bswap16.S bswap32.S bswap64.S
+SRCS+= random.S
+SRCS+= udiv.S urem.S
+
+NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c
+NO_SRCS+= scanc.c skpc.c
diff --git a/sys/lib/libkern/arch/vax/blkcpy.S b/sys/lib/libkern/arch/vax/blkcpy.S
new file mode 100644 (file)
index 0000000..c85518a
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: blkcpy.S,v 1.4 2005/12/11 12:24:45 christos Exp $      */
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <machine/asm.h>
+
+/* __blkcpy(from, to, size) */
+
+ENTRY(__blkcpy, R6)
+       movl    4(%ap),%r1
+       movl    8(%ap),%r3
+       movl    12(%ap),%r6
+       cmpl    %r1,%r3
+       bgtr    2f              # normal forward case
+       blss    3f              # overlapping, must do backwards
+       ret                     # equal, nothing to do
+1:
+       subl2   %r0,%r6
+       movc3   %r0,(%r1),(%r3)
+2:
+       movzwl  $65535,%r0
+       cmpl    %r6,%r0
+       jgtr    1b
+       movc3   %r6,(%r1),(%r3)
+       ret
+3:
+       addl2   %r6,%r1
+       addl2   %r6,%r3
+       movzwl  $65535,%r0
+       jbr     5f
+4:
+       subl2   %r0,%r6
+       subl2   %r0,%r1
+       subl2   %r0,%r3
+       movc3   %r0,(%r1),(%r3)
+       movzwl  $65535,%r0
+       subl2   %r0,%r1
+       subl2   %r0,%r3
+5:
+       cmpl    %r6,%r0
+       jgtr    4b
+       subl2   %r6,%r1
+       subl2   %r6,%r3
+       movc3   %r6,(%r1),(%r3)
+       ret
diff --git a/sys/lib/libkern/arch/vax/blkset.S b/sys/lib/libkern/arch/vax/blkset.S
new file mode 100644 (file)
index 0000000..6c34b7f
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: blkset.S,v 1.5 2005/12/11 12:24:45 christos Exp $      */
+
+/*
+ * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed at Ludd, University of Lule}.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * Set a block of memory larger than 64K.
+ */
+ENTRY(__blkset,R6|R7)
+       movl    4(%ap), %r3
+       movl    8(%ap), %r7
+       movl    12(%ap), %r6
+       jbr     2f
+1:     subl2   %r0, %r6
+       movc5   $0,(%r3),%r7,%r0,(%r3)
+2:     movzwl  $65535,%r0
+       cmpl    %r6, %r0
+       jgtr    1b
+       movc5   $0,(%r3),%r7,%r6,(%r3)
+       ret
diff --git a/sys/lib/libkern/arch/vax/random.S b/sys/lib/libkern/arch/vax/random.S
new file mode 100644 (file)
index 0000000..b1d9e81
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: random.S,v 1.4 2007/01/14 13:26:18 ragge Exp $ */
+
+/*
+ * Copyright (c) 1994 Ludd, University of Lule}, Sweden. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+
+#include <machine/asm.h>
+
+       .data
+randseed:
+       .long   1
+
+ENTRY(random, 0)
+       movl    $16807,%r0
+
+       movl    randseed,%r1            # %r2=16807*loword(randseed)
+       bicl3   $0xffff0000,%r1,%r2
+       mull2   %r0,%r2
+       ashl    $-16,%r1,%r1            # %r1=16807*hiword(randseed)
+       bicl2   $0xffff0000,%r1
+       mull2   %r0,%r1
+       bicl3   $0xffff0000,%r2,%r0
+       ashl    $-16,%r2,%r2            # %r1+=(%r2>>16)
+       bicl2   $0xffff0000,%r2
+       addl2   %r2,%r1
+       ashl    $16,%r1,%r2             # %r0|=%r1<<16
+       bisl2   %r2,%r0
+       ashl    $-16,%r1,%r1            # %r1=%r1>>16
+
+       ashl    $1,%r1,%r1
+       movl    %r0,%r2
+       rotl    $1,%r0,%r0
+       bicl2   $0xfffffffe,%r0
+       bisl2   %r0,%r1
+       movl    %r2,%r0
+       bicl2   $0x80000000,%r0
+       addl2   %r1,%r0
+       bgeq    L1
+       subl2   $0x7fffffff,%r0
+L1:    movl    %r0,randseed
+       ret
diff --git a/sys/lib/libkern/arch/x86_64/Makefile.inc b/sys/lib/libkern/arch/x86_64/Makefile.inc
new file mode 100644 (file)
index 0000000..7a18707
--- /dev/null
@@ -0,0 +1,10 @@
+#      $NetBSD: Makefile.inc,v 1.6 2010/01/14 02:09:46 joerg Exp $
+
+SRCS+= byte_swap_2.S byte_swap_4.S byte_swap_8.S
+SRCS+= ffs.S
+SRCS+= memchr.S memcmp.S memcpy.S memmove.S memset.S
+SRCS+= strcat.S strchr.S strcmp.S
+SRCS+= strcpy.S strlen.S
+SRCS+= strrchr.S
+SRCS+= scanc.S skpc.S
+SRCS+= random.S
diff --git a/sys/lib/libkern/arch/x86_64/random.S b/sys/lib/libkern/arch/x86_64/random.S
new file mode 100644 (file)
index 0000000..cd179e3
--- /dev/null
@@ -0,0 +1,90 @@
+/*     $NetBSD: random.S,v 1.2 2008/04/28 20:24:06 martin Exp $        */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1990,1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ *
+ * Here is a very good random number generator.  This implementation is
+ * based on ``Two Fast Implementations of the "Minimal Standard" Random
+ * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990,
+ * Vol 33 No 1.  Do NOT modify this code unless you have a very thorough
+ * understanding of the algorithm.  It's trickier than you think.  If
+ * you do change it, make sure that its 10,000'th invocation returns
+ * 1043618065.
+ *
+ * Here is easier-to-decipher pseudocode:
+ *
+ * p = (16807*seed)<30:0>      # e.g., the low 31 bits of the product
+ * q = (16807*seed)<62:31>     # e.g., the high 31 bits starting at bit 32
+ * if (p + q < 2^31)
+ *     seed = p + q
+ * else
+ *     seed = ((p + q) & (2^31 - 1)) + 1
+ * return (seed);
+ *
+ * The result is in (0,2^31), e.g., it's always positive.
+ */
+#include <machine/asm.h>
+
+       .data
+randseed:
+       .long   1
+       .text
+ENTRY(random)
+       movl    $16807,%eax
+       imull   randseed(%rip)
+       shld    $1,%eax,%edx
+       andl    $0x7fffffff,%eax
+       addl    %edx,%eax
+       js      1f
+       movl    %eax,randseed(%rip)
+       ret
+1:
+       subl    $0x7fffffff,%eax
+       movl    %eax,randseed(%rip)
+       ret
diff --git a/sys/lib/libkern/arch/x86_64/scanc.S b/sys/lib/libkern/arch/x86_64/scanc.S
new file mode 100644 (file)
index 0000000..93f4e12
--- /dev/null
@@ -0,0 +1,55 @@
+/*     $NetBSD: scanc.S,v 1.2 2008/04/28 20:24:06 martin Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(scanc)
+       movq    %rdx,%r11
+       movb    %cl,%dl
+       movl    %edi,%ecx
+       testl   %ecx,%ecx
+       jz      2f
+       movq    %r11,%rdi
+       xorq    %rax,%rax
+       cld
+1:
+       lodsb
+       testb   %dl,(%rax,%rdi)
+       jnz     2f
+       decl    %ecx
+       jnz     1b
+2:
+       movl    %ecx,%eax
+       ret
diff --git a/sys/lib/libkern/arch/x86_64/skpc.S b/sys/lib/libkern/arch/x86_64/skpc.S
new file mode 100644 (file)
index 0000000..d183b7f
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: skpc.S,v 1.2 2008/04/28 20:24:06 martin Exp $  */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(skpc)
+       movl    %edi,%eax
+       movq    %rsi,%rcx
+       movq    %rdx,%rdi
+       cld
+       repe
+       scasb
+       je      1f
+       incq    %rcx
+1:
+       movl    %ecx,%eax
+       ret
diff --git a/sys/lib/libkern/bcd.c b/sys/lib/libkern/bcd.c
new file mode 100644 (file)
index 0000000..ced51c7
--- /dev/null
@@ -0,0 +1,25 @@
+/* $NetBSD: bcd.c,v 1.1 2006/03/11 15:40:07 kleink Exp $ */
+
+/*
+ * Convert a single byte between (unsigned) packed bcd and binary.
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0,"$NetBSD: bcd.c,v 1.1 2006/03/11 15:40:07 kleink Exp $");
+
+#include <lib/libkern/libkern.h>
+
+unsigned int
+bcdtobin(unsigned int bcd)
+{
+
+        return (((bcd >> 4) & 0x0f) * 10 + (bcd & 0x0f));
+}
+
+unsigned int
+bintobcd(unsigned int bin)
+{
+
+       return ((((bin / 10) << 4) & 0xf0) | (bin % 10));
+}
diff --git a/sys/lib/libkern/crc32.c b/sys/lib/libkern/crc32.c
new file mode 100644 (file)
index 0000000..490b6fc
--- /dev/null
@@ -0,0 +1,116 @@
+/*     $NetBSD: crc32.c,v 1.4 2009/03/26 22:18:14 he Exp $     */
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ *
+ * Adapted from zlib's crc code.
+ *
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors.  This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) Id */
+
+#include <sys/param.h>
+#include <machine/endian.h>
+
+typedef uint32_t u4;
+
+/* Definitions for doing the crc four data bytes at a time. */
+#define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+               (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include <lib/libkern/libkern.h>
+#include "crc32.h"
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+        c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+            crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len)
+{
+    register u4 c;
+    register const u4 *buf4;
+
+    if (buf == NULL) return 0UL;
+
+    c = (u4)crc;
+    c = ~c;
+    while (len && ((uintptr_t)buf & 3)) {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+        len--;
+    }
+
+    buf4 = (const u4 *)(const void *)buf;
+    while (len >= 32) {
+        DOLIT32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOLIT4;
+        len -= 4;
+    }
+    buf = (const unsigned char *)buf4;
+
+    if (len) do {
+        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+    } while (--len);
+    c = ~c;
+    return (uint32_t)c;
+}
+
+#else /* BIG_ENDIAN */
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+        c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+            crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len)
+{
+    register u4 c;
+    register const u4 *buf4;
+
+    if (buf == NULL) return 0UL;
+
+    c = REV((u4)crc);
+    c = ~c;
+    while (len && ((uintptr_t)buf & 3)) {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+        len--;
+    }
+
+    buf4 = (const u4 *)(const void *)buf;
+    buf4--;
+    while (len >= 32) {
+        DOBIG32;
+        len -= 32;
+    }
+    while (len >= 4) {
+        DOBIG4;
+        len -= 4;
+    }
+    buf4++;
+    buf = (const unsigned char *)buf4;
+
+    if (len) do {
+        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+    } while (--len);
+    c = ~c;
+    return (uint32_t)(REV(c));
+}
+#endif
diff --git a/sys/lib/libkern/crc32.h b/sys/lib/libkern/crc32.h
new file mode 100644 (file)
index 0000000..22c2f1b
--- /dev/null
@@ -0,0 +1,441 @@
+/*     $NetBSD: crc32.h,v 1.1 2009/03/25 01:26:13 darran Exp $ */
+
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+static const uint32_t crc_table[8][256] =
+{
+  {
+    0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+    0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+    0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+    0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+    0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+    0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+    0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+    0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+    0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+    0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+    0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+    0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+    0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+    0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+    0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+    0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+    0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+    0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+    0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+    0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+    0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+    0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+    0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+    0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+    0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+    0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+    0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+    0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+    0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+    0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+    0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+    0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+    0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+    0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+    0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+    0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+    0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+    0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+    0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+    0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+    0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+    0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+    0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+    0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+    0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+    0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+    0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+    0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+    0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+    0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+    0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+    0x2d02ef8dUL
+  },
+  {
+    0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+    0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+    0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+    0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+    0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+    0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+    0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+    0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+    0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+    0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+    0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+    0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+    0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+    0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+    0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+    0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+    0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+    0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+    0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+    0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+    0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+    0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+    0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+    0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+    0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+    0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+    0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+    0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+    0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+    0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+    0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+    0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+    0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+    0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+    0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+    0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+    0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+    0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+    0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+    0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+    0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+    0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+    0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+    0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+    0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+    0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+    0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+    0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+    0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+    0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+    0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+    0x9324fd72UL
+  },
+  {
+    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+    0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+    0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+    0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+    0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+    0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+    0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+    0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+    0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+    0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+    0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+    0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+    0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+    0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+    0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+    0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+    0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+    0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+    0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+    0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+    0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+    0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+    0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+    0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+    0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+    0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+    0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+    0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+    0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+    0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+    0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+    0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+    0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+    0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+    0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+    0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+    0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+    0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+    0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+    0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+    0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+    0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+    0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+    0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+    0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+    0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+    0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+    0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+    0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+    0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+    0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+    0xbe9834edUL
+  },
+  {
+    0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+    0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+    0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+    0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+    0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+    0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+    0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+    0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+    0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+    0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+    0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+    0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+    0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+    0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+    0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+    0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+    0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+    0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+    0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+    0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+    0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+    0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+    0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+    0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+    0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+    0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+    0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+    0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+    0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+    0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+    0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+    0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+    0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+    0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+    0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+    0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+    0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+    0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+    0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+    0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+    0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+    0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+    0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+    0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+    0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+    0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+    0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+    0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+    0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+    0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+    0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+    0xde0506f1UL
+  },
+  {
+    0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+    0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+    0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+    0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+    0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+    0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+    0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+    0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+    0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+    0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+    0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+    0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+    0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+    0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+    0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+    0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+    0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+    0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+    0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+    0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+    0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+    0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+    0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+    0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+    0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+    0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+    0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+    0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+    0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+    0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+    0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+    0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+    0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+    0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+    0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+    0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+    0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+    0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+    0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+    0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+    0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+    0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+    0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+    0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+    0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+    0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+    0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+    0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+    0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+    0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+    0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+    0x8def022dUL
+  },
+  {
+    0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+    0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+    0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+    0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+    0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+    0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+    0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+    0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+    0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+    0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+    0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+    0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+    0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+    0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+    0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+    0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+    0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+    0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+    0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+    0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+    0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+    0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+    0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+    0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+    0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+    0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+    0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+    0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+    0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+    0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+    0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+    0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+    0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+    0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+    0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+    0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+    0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+    0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+    0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+    0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+    0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+    0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+    0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+    0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+    0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+    0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+    0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+    0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+    0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+    0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+    0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+    0x72fd2493UL
+  },
+  {
+    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+    0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+    0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+    0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+    0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+    0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+    0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+    0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+    0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+    0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+    0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+    0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+    0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+    0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+    0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+    0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+    0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+    0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+    0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+    0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+    0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+    0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+    0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+    0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+    0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+    0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+    0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+    0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+    0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+    0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+    0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+    0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+    0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+    0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+    0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+    0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+    0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+    0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+    0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+    0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+    0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+    0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+    0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+    0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+    0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+    0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+    0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+    0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+    0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+    0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+    0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+    0xed3498beUL
+  },
+  {
+    0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+    0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+    0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+    0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+    0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+    0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+    0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+    0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+    0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+    0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+    0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+    0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+    0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+    0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+    0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+    0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+    0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+    0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+    0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+    0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+    0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+    0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+    0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+    0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+    0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+    0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+    0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+    0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+    0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+    0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+    0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+    0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+    0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+    0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+    0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+    0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+    0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+    0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+    0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+    0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+    0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+    0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+    0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+    0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+    0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+    0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+    0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+    0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+    0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+    0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+    0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+    0xf10605deUL
+  }
+};
diff --git a/sys/lib/libkern/imax.c b/sys/lib/libkern/imax.c
new file mode 100644 (file)
index 0000000..911bfd4
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: imax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+int
+imax(int a, int b)
+{
+       return (a > b ? a : b);
+}
diff --git a/sys/lib/libkern/imin.c b/sys/lib/libkern/imin.c
new file mode 100644 (file)
index 0000000..0e73f38
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: imin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+int
+imin(int a, int b)
+{
+       return (a < b ? a : b);
+}
diff --git a/sys/lib/libkern/intoa.c b/sys/lib/libkern/intoa.c
new file mode 100644 (file)
index 0000000..2f781b1
--- /dev/null
@@ -0,0 +1,79 @@
+/*     $NetBSD: intoa.c,v 1.3 2009/03/14 15:36:22 dsl Exp $    */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
+ */
+
+#include <sys/types.h>
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <lib/libkern/libkern.h>
+#else
+char *intoa(u_int32_t); /* XXX */
+#endif
+
+/* Similar to inet_ntoa() */
+char *
+intoa(u_int32_t addr)
+{
+       char *cp;
+       u_int byte;
+       int n;
+       static char buf[17];    /* strlen(".255.255.255.255") + 1 */
+
+       addr = ntohl(addr);
+       cp = &buf[sizeof buf];
+       *--cp = '\0';
+
+       n = 4;
+       do {
+               byte = addr & 0xff;
+               *--cp = byte % 10 + '0';
+               byte /= 10;
+               if (byte > 0) {
+                       *--cp = byte % 10 + '0';
+                       byte /= 10;
+                       if (byte > 0)
+                               *--cp = byte + '0';
+               }
+               *--cp = '.';
+               addr >>= 8;
+       } while (--n > 0);
+
+       return (cp+1);
+}
diff --git a/sys/lib/libkern/kern_assert.c b/sys/lib/libkern/kern_assert.c
new file mode 100644 (file)
index 0000000..5880a7d
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD: kern_assert.c,v 1.2 2011/09/29 20:50:09 christos Exp $ */
+
+/*
+ * Copyright (c) 1996 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#endif
+
+void
+kern_assert(const char *fmt, ...)
+{
+       va_list ap;
+#ifdef _KERNEL
+       if (panicstr != NULL)
+               return;
+#endif
+       va_start(ap, fmt);
+       vpanic(fmt, ap);
+       va_end(ap);
+}
diff --git a/sys/lib/libkern/libkern.h b/sys/lib/libkern/libkern.h
new file mode 100644 (file)
index 0000000..e6fc8b8
--- /dev/null
@@ -0,0 +1,346 @@
+/*     $NetBSD: libkern.h,v 1.104 2011/11/28 08:05:06 tls Exp $        */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)libkern.h   8.2 (Berkeley) 8/5/94
+ */
+
+#ifndef _LIB_LIBKERN_LIBKERN_H_
+#define _LIB_LIBKERN_LIBKERN_H_
+
+#include <sys/types.h>
+#include <sys/inttypes.h>
+#include <sys/null.h>
+
+#ifndef LIBKERN_INLINE
+#define LIBKERN_INLINE static __inline
+#define LIBKERN_BODY
+#endif
+
+LIBKERN_INLINE int imax(int, int) __unused;
+LIBKERN_INLINE int imin(int, int) __unused;
+LIBKERN_INLINE u_int max(u_int, u_int) __unused;
+LIBKERN_INLINE u_int min(u_int, u_int) __unused;
+LIBKERN_INLINE long lmax(long, long) __unused;
+LIBKERN_INLINE long lmin(long, long) __unused;
+LIBKERN_INLINE u_long ulmax(u_long, u_long) __unused;
+LIBKERN_INLINE u_long ulmin(u_long, u_long) __unused;
+LIBKERN_INLINE int abs(int) __unused;
+
+LIBKERN_INLINE int isspace(int) __unused;
+LIBKERN_INLINE int isascii(int) __unused;
+LIBKERN_INLINE int isupper(int) __unused;
+LIBKERN_INLINE int islower(int) __unused;
+LIBKERN_INLINE int isalpha(int) __unused;
+LIBKERN_INLINE int isdigit(int) __unused;
+LIBKERN_INLINE int isxdigit(int) __unused;
+LIBKERN_INLINE int toupper(int) __unused;
+LIBKERN_INLINE int tolower(int) __unused;
+
+#ifdef LIBKERN_BODY
+LIBKERN_INLINE int
+imax(int a, int b)
+{
+       return (a > b ? a : b);
+}
+LIBKERN_INLINE int
+imin(int a, int b)
+{
+       return (a < b ? a : b);
+}
+LIBKERN_INLINE long
+lmax(long a, long b)
+{
+       return (a > b ? a : b);
+}
+LIBKERN_INLINE long
+lmin(long a, long b)
+{
+       return (a < b ? a : b);
+}
+LIBKERN_INLINE u_int
+max(u_int a, u_int b)
+{
+       return (a > b ? a : b);
+}
+LIBKERN_INLINE u_int
+min(u_int a, u_int b)
+{
+       return (a < b ? a : b);
+}
+LIBKERN_INLINE u_long
+ulmax(u_long a, u_long b)
+{
+       return (a > b ? a : b);
+}
+LIBKERN_INLINE u_long
+ulmin(u_long a, u_long b)
+{
+       return (a < b ? a : b);
+}
+
+LIBKERN_INLINE int
+abs(int j)
+{
+       return(j < 0 ? -j : j);
+}
+
+LIBKERN_INLINE int
+isspace(int ch)
+{
+       return (ch == ' ' || (ch >= '\t' && ch <= '\r'));
+}
+
+LIBKERN_INLINE int
+isascii(int ch)
+{
+       return ((ch & ~0x7f) == 0);
+}
+
+LIBKERN_INLINE int
+isupper(int ch)
+{
+       return (ch >= 'A' && ch <= 'Z');
+}
+
+LIBKERN_INLINE int
+islower(int ch)
+{
+       return (ch >= 'a' && ch <= 'z');
+}
+
+LIBKERN_INLINE int
+isalpha(int ch)
+{
+       return (isupper(ch) || islower(ch));
+}
+
+LIBKERN_INLINE int
+isdigit(int ch)
+{
+       return (ch >= '0' && ch <= '9');
+}
+
+LIBKERN_INLINE int
+isxdigit(int ch)
+{
+       return (isdigit(ch) ||
+           (ch >= 'A' && ch <= 'F') ||
+           (ch >= 'a' && ch <= 'f'));
+}
+
+LIBKERN_INLINE int
+toupper(int ch)
+{
+       if (islower(ch))
+               return (ch - 0x20);
+       return (ch);
+}
+
+LIBKERN_INLINE int
+tolower(int ch)
+{
+       if (isupper(ch))
+               return (ch + 0x20);
+       return (ch);
+}
+#endif
+
+#define        __NULL_STMT             do { } while (/* CONSTCOND */ 0)
+
+#define __KASSERTSTR  "kernel %sassertion \"%s\" failed: file \"%s\", line %d "
+
+#ifdef NDEBUG                                          /* tradition! */
+#define        assert(e)       ((void)0)
+#else
+#define        assert(e)       (__predict_true((e)) ? (void)0 :                    \
+                           kern_assert(__KASSERTSTR, "", #e, __FILE__, __LINE__))
+#endif
+
+#ifdef __COVERITY__
+#ifndef DIAGNOSTIC
+#define DIAGNOSTIC
+#endif
+#endif
+
+#define        CTASSERT(x)             __CTASSERT(x)
+
+#ifndef DIAGNOSTIC
+#define _DIAGASSERT(a) (void)0
+#ifdef lint
+#define        KASSERTMSG(e, msg, ...) /* NOTHING */
+#define        KASSERT(e)              /* NOTHING */
+#else /* !lint */
+#define        KASSERTMSG(e, msg, ...) ((void)0)
+#define        KASSERT(e)              ((void)0)
+#endif /* !lint */
+#else /* DIAGNOSTIC */
+#define _DIAGASSERT(a) assert(a)
+#define        KASSERTMSG(e, msg, ...)         \
+                       (__predict_true((e)) ? (void)0 :                    \
+                           kern_assert(__KASSERTSTR msg, "diagnostic ", #e,        \
+                               __FILE__, __LINE__, ## __VA_ARGS__))
+
+#define        KASSERT(e)      (__predict_true((e)) ? (void)0 :                    \
+                           kern_assert(__KASSERTSTR, "diagnostic ", #e,            \
+                               __FILE__, __LINE__))
+#endif
+
+#ifndef DEBUG
+#ifdef lint
+#define        KDASSERTMSG(e,msg, ...) /* NOTHING */
+#define        KDASSERT(e)             /* NOTHING */
+#else /* lint */
+#define        KDASSERTMSG(e,msg, ...) ((void)0)
+#define        KDASSERT(e)             ((void)0)
+#endif /* lint */
+#else
+#define        KDASSERTMSG(e, msg, ...)        \
+                       (__predict_true((e)) ? (void)0 :                    \
+                           kern_assert(__KASSERTSTR msg, "debugging ", #e,         \
+                               __FILE__, __LINE__, ## __VA_ARGS__))
+
+#define        KDASSERT(e)     (__predict_true((e)) ? (void)0 :                    \
+                           kern_assert(__KASSERTSTR, "debugging ", #e,     \
+                               __FILE__, __LINE__))
+#endif
+
+/*
+ * XXX: For compatibility we use SMALL_RANDOM by default.
+ */
+#define SMALL_RANDOM
+
+#ifndef offsetof
+#if __GNUC_PREREQ__(4, 0)
+#define offsetof(type, member) __builtin_offsetof(type, member)
+#else
+#define        offsetof(type, member) \
+    ((size_t)(unsigned long)(&(((type *)0)->member)))
+#endif
+#endif
+
+#define        MTPRNG_RLEN             624
+struct mtprng_state {
+       unsigned int mt_idx; 
+       uint32_t mt_elem[MTPRNG_RLEN];
+       uint32_t mt_count;
+       uint32_t mt_sparse[3];
+};
+
+/* Prototypes for which GCC built-ins exist. */
+void   *memcpy(void *, const void *, size_t);
+int     memcmp(const void *, const void *, size_t);
+void   *memset(void *, int, size_t);
+#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE)
+#define        memcpy(d, s, l)         __builtin_memcpy(d, s, l)
+#define        memcmp(a, b, l)         __builtin_memcmp(a, b, l)
+#endif
+#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE)
+#define        memset(d, v, l)         __builtin_memset(d, v, l)
+#endif
+
+char   *strcpy(char *, const char *);
+int     strcmp(const char *, const char *);
+size_t  strlen(const char *);
+size_t  strnlen(const char *, size_t);
+char   *strsep(char **, const char *);
+#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE)
+#define        strcpy(d, s)            __builtin_strcpy(d, s)
+#define        strcmp(a, b)            __builtin_strcmp(a, b)
+#define        strlen(a)               __builtin_strlen(a)
+#endif
+
+/* Functions for which we always use built-ins. */
+#ifdef __GNUC__
+#define        alloca(s)               __builtin_alloca(s)
+#endif
+
+/* These exist in GCC 3.x, but we don't bother. */
+char   *strcat(char *, const char *);
+char   *strncpy(char *, const char *, size_t);
+int     strncmp(const char *, const char *, size_t);
+char   *strchr(const char *, int);
+char   *strrchr(const char *, int);
+
+char   *strstr(const char *, const char *);
+
+/*
+ * ffs is an instruction on vax.
+ */
+int     ffs(int);
+#if __GNUC_PREREQ__(2, 95) && (!defined(__vax__) || __GNUC_PREREQ__(4,1))
+#define        ffs(x)          __builtin_ffs(x)
+#endif
+
+void    kern_assert(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+unsigned int
+       bcdtobin(unsigned int);
+unsigned int
+       bintobcd(unsigned int);
+u_int32_t
+       inet_addr(const char *);
+struct in_addr;
+int    inet_aton(const char *, struct in_addr *);
+char   *intoa(u_int32_t);
+#define inet_ntoa(a) intoa((a).s_addr)
+void   *memchr(const void *, int, size_t);
+void   *memmove(void *, const void *, size_t);
+int     pmatch(const char *, const char *, const char **);
+#ifndef SMALL_RANDOM
+void    srandom(unsigned long);
+char   *initstate(unsigned long, char *, size_t);
+char   *setstate(char *);
+#endif /* SMALL_RANDOM */
+long    random(void);
+void    mtprng_init32(struct mtprng_state *, uint32_t);
+void    mtprng_initarray(struct mtprng_state *, const uint32_t *, size_t);
+uint32_t mtprng_rawrandom(struct mtprng_state *);
+uint32_t mtprng_random(struct mtprng_state *);
+int     scanc(u_int, const u_char *, const u_char *, int);
+int     skpc(int, size_t, u_char *);
+int     strcasecmp(const char *, const char *);
+size_t  strlcpy(char *, const char *, size_t);
+size_t  strlcat(char *, const char *, size_t);
+int     strncasecmp(const char *, const char *, size_t);
+u_long  strtoul(const char *, char **, int);
+long long strtoll(const char *, char **, int);
+unsigned long long strtoull(const char *, char **, int);
+uintmax_t strtoumax(const char *, char **, int);
+int     snprintb(char *, size_t, const char *, uint64_t);
+int     snprintb_m(char *, size_t, const char *, uint64_t, size_t);
+int     kheapsort(void *, size_t, size_t, int (*)(const void *, const void *),
+                  void *);
+uint32_t crc32(uint32_t, const uint8_t *, size_t);
+unsigned int   popcount(unsigned int) __constfunc;
+unsigned int   popcountl(unsigned long) __constfunc;
+unsigned int   popcountll(unsigned long long) __constfunc;
+unsigned int   popcount32(uint32_t) __constfunc;
+unsigned int   popcount64(uint64_t) __constfunc;
+#endif /* !_LIB_LIBKERN_LIBKERN_H_ */
diff --git a/sys/lib/libkern/lmax.c b/sys/lib/libkern/lmax.c
new file mode 100644 (file)
index 0000000..cabb7b1
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: lmax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+long
+lmax(long a, long b)
+{
+       return (a > b ? a : b);
+}
diff --git a/sys/lib/libkern/lmin.c b/sys/lib/libkern/lmin.c
new file mode 100644 (file)
index 0000000..ef49b77
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: lmin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+long
+lmin(long a, long b)
+{
+       return (a < b ? a : b);
+}
diff --git a/sys/lib/libkern/max.c b/sys/lib/libkern/max.c
new file mode 100644 (file)
index 0000000..eae7bdc
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: max.c,v 1.6 2009/03/14 21:04:24 dsl Exp $      */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+unsigned int
+max(unsigned int a, unsigned int b)
+{
+       return (a > b ? a : b);
+}
diff --git a/sys/lib/libkern/mertwist.c b/sys/lib/libkern/mertwist.c
new file mode 100644 (file)
index 0000000..3613449
--- /dev/null
@@ -0,0 +1,222 @@
+/*     $NetBSD: mertwist.c,v 1.8 2008/04/28 20:24:06 martin Exp $      */
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <lib/libkern/libkern.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+#define        KASSERT(x)      assert(x)
+#endif
+
+/*
+ * Mersenne Twister.  Produces identical output compared to mt19937ar.c
+ * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ */
+
+#define        MATRIX_A(a)             (((a) & 1) ? 0x9908b0df : 0)
+#define        TEMPERING_MASK_B        0x9d2c5680
+#define        TEMPERING_MASK_C        0xefc60000
+#define        UPPER_MASK              0x80000000
+#define        LOWER_MASK              0x7fffffff
+#define        MIX(u,l)                (((u) & UPPER_MASK) | ((l) & LOWER_MASK))
+
+#define        KNUTH_MULTIPLIER        0x6c078965
+
+#ifndef MTPRNG_RLEN
+#define        MTPRNG_RLEN             624
+#endif
+#define        MTPRNG_POS1             397
+
+static void mtprng_refresh(struct mtprng_state *);
+
+/*
+ * Initialize the generator from a seed
+ */
+void
+mtprng_init32(struct mtprng_state *mt, uint32_t seed)
+{
+       size_t i;
+
+       /*
+        * Use Knuth's algorithm for expanding this seed over its
+        * portion of the key space.
+        */
+       mt->mt_elem[0] = seed;
+       for (i = 1; i < MTPRNG_RLEN; i++) {
+               mt->mt_elem[i] = KNUTH_MULTIPLIER
+                   * (mt->mt_elem[i-1] ^ (mt->mt_elem[i-1] >> 30)) + i;
+       }
+
+       mtprng_refresh(mt);
+}
+
+void
+mtprng_initarray(struct mtprng_state *mt, const uint32_t *key, size_t keylen)
+{
+       uint32_t *mp;
+       size_t i, j, k;
+
+       /*
+        * Use Knuth's algorithm for expanding this seed over its
+        * portion of the key space.
+        */
+       mt->mt_elem[0] = 19650218UL;
+       for (i = 1; i < MTPRNG_RLEN; i++) {
+               mt->mt_elem[i] = KNUTH_MULTIPLIER
+                   * (mt->mt_elem[i-1] ^ (mt->mt_elem[i-1] >> 30)) + i;
+       }
+
+       KASSERT(keylen > 0);
+
+       i = 1;
+       j = 0;
+       k = (keylen < MTPRNG_RLEN ? MTPRNG_RLEN : keylen);
+
+       mp = &mt->mt_elem[1];
+       for (; k-- > 0; mp++) {
+               mp[0] ^= (mp[-1] ^ (mp[-1] >> 30)) * 1664525UL;
+               mp[0] += key[j] + j;
+               if (++i == MTPRNG_RLEN) {
+                       KASSERT(mp == mt->mt_elem + MTPRNG_RLEN - 1);
+                       mt->mt_elem[0] = mp[0];
+                       i = 1;
+                       mp = mt->mt_elem;
+               }
+               if (++j == keylen)
+                       j = 0;
+       }
+       for (j = MTPRNG_RLEN; --j > 0; mp++) {
+               mp[0] ^= (mp[-1] ^ (mp[-1] >> 30)) * 1566083941UL;
+               mp[0] -= i;
+               if (++i == MTPRNG_RLEN) {
+                       KASSERT(mp == mt->mt_elem + MTPRNG_RLEN - 1);
+                       mt->mt_elem[0] = mp[0];
+                       i = 1;
+                       mp = mt->mt_elem;
+               }
+       }
+       mt->mt_elem[0] = 0x80000000;
+       mtprng_refresh(mt);
+}
+
+/*
+ * Generate an array of 624 untempered numbers
+ */
+void
+mtprng_refresh(struct mtprng_state *mt)
+{
+       uint32_t y;
+       size_t i, j;
+       /*
+        * The following has been refactored to avoid the need for 'mod 624'
+       */
+       for (i = 0, j = MTPRNG_POS1; j < MTPRNG_RLEN; i++, j++) {
+               y = MIX(mt->mt_elem[i], mt->mt_elem[i+1]);
+               mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y);
+       }
+       for (j = 0; i < MTPRNG_RLEN - 1; i++, j++) {
+               y = MIX(mt->mt_elem[i], mt->mt_elem[i+1]);
+               mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y);
+       }
+       y = MIX(mt->mt_elem[MTPRNG_RLEN - 1], mt->mt_elem[0]);
+       mt->mt_elem[MTPRNG_RLEN - 1] =
+           mt->mt_elem[MTPRNG_POS1 - 1] ^ (y >> 1) ^ MATRIX_A(y);
+}
+/*
+ * Extract a tempered PRN based on the current index.  Then recompute a
+ * new value for the index.  This avoids having to regenerate the array
+ * every 624 iterations. We can do this since recomputing only the next
+ * element and the [(i + 397) % 624] one.
+ */
+uint32_t
+mtprng_rawrandom(struct mtprng_state *mt)
+{
+       uint32_t x, y;
+       const size_t i = mt->mt_idx;
+       size_t j;
+
+       /*
+        * First generate the random value for the current position.
+        */
+       x = mt->mt_elem[i];
+       x ^= x >> 11;
+       x ^= (x << 7) & TEMPERING_MASK_B;
+       x ^= (x << 15) & TEMPERING_MASK_C;
+       x ^= x >> 18;
+
+       /*
+        * Next recalculate the next sequence for the current position.
+        */
+       y = mt->mt_elem[i];
+       if (__predict_true(i < MTPRNG_RLEN - 1)) {
+               /*
+                * Avoid doing % since it can be expensive.
+                * j = (i + MTPRNG_POS1) % MTPRNG_RLEN;
+                */
+               j = i + MTPRNG_POS1;
+               if (j >= MTPRNG_RLEN)
+                       j -= MTPRNG_RLEN;
+               mt->mt_idx++;
+       } else {
+               j = MTPRNG_POS1 - 1;
+               mt->mt_idx = 0;
+       }
+       y = MIX(y, mt->mt_elem[mt->mt_idx]);
+       mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y);
+
+       /*
+        * Return the value calculated in the first step.
+        */
+       return x;
+}
+
+/*
+ * This is a non-standard routine which attempts to return a cryptographically
+ * strong random number by collapsing 2 32bit values outputed by the twister
+ * into one 32bit value.  
+ */
+uint32_t
+mtprng_random(struct mtprng_state *mt)
+{
+       uint32_t a;
+
+       mt->mt_count = (mt->mt_count + 13) & 31;
+       a = mtprng_rawrandom(mt);
+       a = (a << mt->mt_count) | (a >> (32 - mt->mt_count));
+       return a + mtprng_rawrandom(mt);
+}
diff --git a/sys/lib/libkern/milieu.h b/sys/lib/libkern/milieu.h
new file mode 100644 (file)
index 0000000..863a28c
--- /dev/null
@@ -0,0 +1,147 @@
+/* $NetBSD: milieu.h,v 1.3 2008/04/28 20:24:06 martin Exp $ */
+
+/* This is a derivative work. */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ross Harvey.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+===============================================================================
+
+This C header file is part of TestFloat, Release 2a, a package of programs
+for testing the correctness of floating-point arithmetic complying to the
+IEC/IEEE Standard for Floating-Point.
+
+Written by John R. Hauser.  More information is available through the Web
+page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#ifndef MILIEU_H
+#define MILIEU_H
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <inttypes.h>
+#else
+#include <sys/inttypes.h>
+#endif
+
+#include <sys/endian.h>
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define LITTLEENDIAN
+#else
+#define BIGENDIAN
+#endif
+
+#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified.  For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits.  The `flag' type must be able to hold either a 0 or 1.  For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef unsigned int uint8;
+typedef signed int int8;
+typedef unsigned int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef uint64_t uint64;
+typedef int64_t int64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified.  For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef uint8_t bits8;
+typedef int8_t sbits8;
+typedef uint16_t bits16;
+typedef int16_t sbits16;
+typedef uint32_t bits32;
+typedef int32_t sbits32;
+#ifdef BITS64
+typedef uint64_t bits64;
+typedef int64_t sbits64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and
+if necessary ``marks'' the literal as having a 64-bit integer type.
+For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type.  Some compilers may allow `LIT64' to be
+defined as the identity macro:  `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined.  If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE static inline
+
+#endif
diff --git a/sys/lib/libkern/min.c b/sys/lib/libkern/min.c
new file mode 100644 (file)
index 0000000..935c06d
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: min.c,v 1.6 2009/03/14 21:04:24 dsl Exp $      */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+unsigned int
+min(unsigned int a, unsigned int b)
+{
+       return (a < b ? a : b);
+}
diff --git a/sys/lib/libkern/pmatch.c b/sys/lib/libkern/pmatch.c
new file mode 100644 (file)
index 0000000..fe7f619
--- /dev/null
@@ -0,0 +1,130 @@
+/*     $NetBSD: pmatch.c,v 1.6 2009/03/14 21:04:24 dsl Exp $   */
+
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <lib/libkern/libkern.h>
+/*
+ * pmatch():
+ *     Return 2 on exact match.
+ *     Return 1 on substring match.
+ *     Return 0 on no match.
+ *     Return -1 on error.
+ * *estr will point to the end of thelongest exact or substring match.
+ */
+int
+pmatch(const char *string, const char *pattern, const char **estr)
+{
+       u_char stringc, patternc, rangec;
+       int match, negate_range;
+       const char *oestr, *pestr, *testr;
+
+       if (estr == NULL)
+               estr = &testr;
+
+       for (;; ++string) {
+               stringc = *string;
+               switch (patternc = *pattern++) {
+               case 0:
+                       *estr = string;
+                       return stringc == '\0' ? 2 : 1;
+               case '?':
+                       if (stringc == '\0')
+                               return 0;
+                       *estr = string;
+                       break;
+               case '*':
+                       if (!*pattern) {
+                               while (*string)
+                                       string++;
+                               *estr = string;
+                               return 2;
+                       }
+                       oestr = *estr;
+                       pestr = NULL;
+
+                       do {
+                               switch (pmatch(string, pattern, estr)) {
+                               case -1:
+                                       return -1;
+                               case 0:
+                                       break;
+                               case 1:
+                                       pestr = *estr;
+                                       break;
+                               case 2:
+                                       return 2;
+                               default:
+                                       return -1;
+                               }
+                               *estr = string;
+                       }
+                       while (*string++);
+
+                       if (pestr) {
+                               *estr = pestr;
+                               return 1;
+                       } else {
+                               *estr = oestr;
+                               return 0;
+                       }
+
+               case '[':
+                       match = 0;
+                       if ((negate_range = (*pattern == '^')) != 0)
+                               pattern++;
+                       while ((rangec = *pattern++) != '\0') {
+                               if (rangec == ']')
+                                       break;
+                               if (match)
+                                       continue;
+                               if (rangec == '-' && *(pattern - 2) != '[' &&
+                                   *pattern != ']') {
+                                       match =
+                                           stringc <= (u_char)*pattern &&
+                                           (u_char)*(pattern - 2) <= stringc;
+                                       pattern++;
+                               } else
+                                       match = (stringc == rangec);
+                       }
+                       if (rangec == 0)
+                               return -1;
+                       if (match == negate_range)
+                               return 0;
+                       *estr = string;
+                       break;
+               default:
+                       if (patternc != stringc)
+                               return 0;
+                       *estr = string;
+                       break;
+               }
+       }
+}
diff --git a/sys/lib/libkern/rngtest.c b/sys/lib/libkern/rngtest.c
new file mode 100644 (file)
index 0000000..c20263e
--- /dev/null
@@ -0,0 +1,281 @@
+/*     $NetBSD: rngtest.c,v 1.2 2011/11/25 12:45:00 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Thor Lancelot Simon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* fips140.c   1.5 (Qualcomm) 02/09/02 */
+/*
+This software is free for commercial and non-commercial use
+subject to the following conditions.
+
+Copyright remains vested in QUALCOMM Incorporated, and Copyright
+notices in the code are not to be removed.  If this package is used in
+a product, QUALCOMM should be given attribution as the author this
+software.  This can be in the form of a textual message at program
+startup or in documentation (online or textual) provided with the
+package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the
+   distribution.
+
+3. All advertising materials mentioning features or use of this
+   software must display the following acknowledgement:  This product
+   includes software developed by QUALCOMM Incorporated.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+The license and distribution terms for any publically available version
+or derivative of this code cannot be changed, that is, this code cannot
+simply be copied and put under another distribution license including
+the GNU Public License.
+*/
+
+/* Run FIPS 140 statistical tests on a file */
+
+/* written by Greg Rose, Copyright C 2000 QUALCOMM Incorporated */
+
+/*
+ * Modified for in-kernel use (API adjustments, conversion from
+ * floating to fixed-point chi-sq computation) by Thor Lancelot
+ * Simon.
+ *
+ * A comment on appropriate use of this test and the infamous FIPS 140
+ * "continuous output test" (COT):  Both tests are very appropriate for
+ * software interfaces to hardware implementations, and will quickly tell
+ * you if any number of very bad things have happened to your RNG: perhaps
+ * it has come disconnected from the rest of the system, somehow, and you
+ * are getting only unconditioned bus noise (read: clock edges from the
+ * loudest thing in your system).  Perhaps it has ceased to latch a shift
+ * register and is feeding you the same data over and over again.  Perhaps
+ * it is not really random at all but was sold to you as such.  Perhaps it
+ * is not actually *there* (Intel chipset RNG anyone?) but claims to be,
+ * and is feeding you 01010101 on every register read.
+ *
+ * However, when applied to software RNGs, the situation is quite different.
+ * Most software RNGs use a modern hash function or cipher as an output
+ * stage.  The resulting bitstream assuredly *should* pass both the
+ * "continuous output" (no two consecutive samples identical) and
+ * statistical tests: if it does not, the cryptographic primitive or its
+ * implementation is terribly broken.
+ *
+ * There is still value to this test: it will tell you if you inadvertently
+ * terribly break your implementation of the software RNG.  Which is a thing
+ * that has in fact happened from time to time, even to the careful (or
+ * paranoid).  But it will not tell you if there is a problem with the
+ * _input_ to that final cryptographic primitive -- the bits that are hashed
+ * or the key to the cipher -- and if an adversary can find one, you're
+ * still toast.
+ *
+ * The situation is -- sadly -- similar with hardware RNGs that are
+ * certified to one of the standards such as X9.31 or SP800-90.  In these
+ * cases the hardware vendor has hidden the actual random bitstream behind
+ * a hardware cipher/hash implementation that should, indeed, produce good
+ * quality random numbers that pass will pass this test -- whether the
+ * underlying bitstream is trustworthy or not.
+ *
+ * However, this test (and the COT) will still probably tell you if the
+ * thing fell off the bus, etc.  Which is a thing that has in fact
+ * happened from time to time, even to the fully certified...
+ *
+ * This module does not (yet?) implement the Continuous Output Test.  When
+ * I call that test "infamous", it's because it obviously reduces the
+ * backtracking resistance of any implementation that includes it -- the
+ * implementation has to store the entire previous RNG output in order to
+ * perform the required comparison; not just periodically but all the time
+ * when operating at all.  Nonetheless, it has obvious value for
+ * hardware implementations where it will quickly and surely detect a
+ * severe failure; but as of this writing several of the latest comments
+ * on SP800-90 recommend removing any requirement for the COT and my
+ * personal tendency is to agree.  It's easy to add if you really need it.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/rngtest.h>
+
+#include <lib/libkern/libkern.h>
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: rngtest.c,v 1.2 2011/11/25 12:45:00 joerg Exp $");
+
+#ifndef _KERNEL
+static inline int
+printf(const char * __restrict format, ...)
+{
+       return 0;       /* XXX no standard way to do output in libkern? */
+}
+#endif
+
+int bitnum = 0;
+
+const int minrun[7] = {0, 2315, 1114, 527, 240, 103, 103};
+const int maxrun[7] = {0, 2685, 1386, 723, 384, 209, 209};
+#define LONGRUN        26
+#define MINONES 9725
+#define MAXONES 10275
+#define MINPOKE 2.16
+#define MAXPOKE 46.17
+#define PRECISION 100000
+
+const int longrun = LONGRUN;
+const int minones = MINONES;
+const int maxones = MAXONES;
+const long long minpoke = (MINPOKE * PRECISION);
+const long long maxpoke = (MAXPOKE * PRECISION);
+
+/* Population count of 1's in a byte */
+const unsigned char Popcount[] = {
+       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+/* end of run */
+static void
+endrun(rngtest_t *const rc, const int last, int run)
+{
+       if (run >= longrun) {
+               printf("Kernel RNG \"%s\" long run test FAILURE: "
+                      "Run of %d %ds found\n", rc->rt_name, run, last);
+               ++rc->rt_nerrs;
+       }
+       if (run > 6)
+               run = 6;
+       ++rc->rt_runs[last][run];
+}
+
+int
+rngtest(rngtest_t *const rc)
+{
+       int i;
+       uint8_t *p;
+       int c;
+       long long X;
+       int last;
+       int run;
+
+       /* Enforce sanity for most members of the context */
+       memset(rc->rt_poker, 0, sizeof(rc->rt_poker));
+       memset(rc->rt_runs, 0, sizeof(rc->rt_runs));
+       rc->rt_nerrs = 0;
+       rc->rt_name[sizeof(rc->rt_name) - 1] = '\0';
+
+       /* monobit test */
+       for (p = rc->rt_b, c = 0; p < &rc->rt_b[sizeof rc->rt_b]; ++p)
+               c += Popcount[*p];
+       if (c <= minones || maxones <= c) {
+               printf("Kernel RNG \"%s\" monobit test FAILURE: %d ones\n",
+                      rc->rt_name, c);
+               ++rc->rt_nerrs;
+       }
+       /* poker test */
+       for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
+               ++rc->rt_poker[*p & 0xF];
+               ++rc->rt_poker[(*p >> 4) & 0xF];
+       }
+       for (X = i = 0; i < 16; ++i) {
+               X += rc->rt_poker[i] * rc->rt_poker[i];
+       }
+       X *= PRECISION;
+       X = 16 * X / 5000 - 5000 * PRECISION;
+       if (X <= minpoke || maxpoke <= X) {
+               printf("Kernel RNG \"%s\" poker test failure: "
+                      "parameter X = %lld.%lld\n", rc->rt_name,
+                      (X / PRECISION), (X % PRECISION));
+               ++rc->rt_nerrs;
+       }
+       /* runs test */
+       last = (rc->rt_b[0] >> 7) & 1;
+       run = 0;
+       for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
+               c = *p;
+               for (i = 7; i >= 0; --i) {
+                       if (((c >> i) & 1) != last) {
+                               endrun(rc, last, run);
+                               run = 0;
+                               last = (c >> i) & 1;
+                       }
+                       ++run;
+               }
+       }
+       endrun(rc, last, run);
+
+       for (run = 1; run <= 6; ++run) {
+               for (last = 0; last <= 1; ++last) {
+                       if (rc->rt_runs[last][run] <= minrun[run]) {
+                               printf("Kernel RNG \"%s\" runs test FAILURE: "
+                                      "too few runs of %d %ds (%d < %d)\n",
+                                      rc->rt_name, run, last,
+                                      rc->rt_runs[last][run], minrun[run]);
+                               ++rc->rt_nerrs;
+                       } else if (rc->rt_runs[last][run] >= maxrun[run]) {
+                               printf("Kernel RNG \"%s\" runs test FAILURE: "
+                                      "too many runs of %d %ds (%d > %d)\n",
+                                      rc->rt_name, run, last,
+                                      rc->rt_runs[last][run], maxrun[run]);
+                               ++rc->rt_nerrs;
+                       }
+               }
+       }
+       memset(rc->rt_b, 0, sizeof(rc->rt_b));
+       return rc->rt_nerrs;
+}
diff --git a/sys/lib/libkern/scanc.c b/sys/lib/libkern/scanc.c
new file mode 100644 (file)
index 0000000..7c8ebbc
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: scanc.c,v 1.8 2005/12/11 12:24:37 christos Exp $       */
+
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ufs_subr.c  7.13 (Berkeley) 6/28/90
+ */
+
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+
+int
+scanc(u_int size, const u_char *cp, const u_char table[], int mask)
+{
+       const u_char *end = &cp[size];
+
+       while (cp < end && (table[*cp] & mask) == 0)
+               cp++;
+       return (end - cp);
+}
diff --git a/sys/lib/libkern/skpc.c b/sys/lib/libkern/skpc.c
new file mode 100644 (file)
index 0000000..36b94ab
--- /dev/null
@@ -0,0 +1,45 @@
+/*     $NetBSD: skpc.c,v 1.7 2009/03/14 15:36:22 dsl Exp $     */
+
+/*
+ * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ufs_subr.c  7.13 (Berkeley) 6/28/90
+ */
+
+#include <sys/types.h>
+#include <lib/libkern/libkern.h>
+
+int
+skpc(int mask, size_t size, u_char *cp)
+{
+       u_char *end = &cp[size];
+
+       while (cp < end && *cp == (u_char) mask)
+               cp++;
+       return (end - cp);
+}
diff --git a/sys/lib/libkern/softfloat-macros.h b/sys/lib/libkern/softfloat-macros.h
new file mode 100644 (file)
index 0000000..499a486
--- /dev/null
@@ -0,0 +1,745 @@
+/* $NetBSD: softfloat-macros.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser.  This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704.  Funding was partially provided by the
+National Science Foundation under grant MIP-9311980.  The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'.  If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1.  The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 32, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
+{
+    bits32 z;
+
+    if ( count == 0 ) {
+        z = a;
+    }
+    else if ( count < 32 ) {
+        z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
+    }
+    else {
+        z = ( a != 0 );
+    }
+    *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'.  If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1.  The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 64, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
+{
+    bits64 z;
+
+    if ( count == 0 ) {
+        z = a;
+    }
+    else if ( count < 64 ) {
+        z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
+    }
+    else {
+        z = ( a != 0 );
+    }
+    *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
+_plus_ the number of bits given in `count'.  The shifted result is at most
+64 nonzero bits; this is stored at the location pointed to by `z0Ptr'.  The
+bits shifted off form a second 64-bit result as follows:  The _last_ bit
+shifted off is the most-significant bit of the extra result, and the other
+63 bits of the extra result are all zero if and only if _all_but_the_last_
+bits shifted off were all zero.  This extra result is stored in the location
+pointed to by `z1Ptr'.  The value of `count' can be arbitrarily large.
+    (This routine makes more sense if `a0' and `a1' are considered to form a
+fixed-point value with binary point between `a0' and `a1'.  This fixed-point
+value is shifted right by the number of bits given in `count', and the
+integer part of the result is returned at the location pointed to by
+`z0Ptr'.  The fractional part of the result may be slightly corrupted as
+described above, and is returned at the location pointed to by `z1Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64ExtraRightJamming(
+     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+    bits64 z0, z1;
+    int8 negCount = ( - count ) & 63;
+
+    if ( count == 0 ) {
+        z1 = a1;
+        z0 = a0;
+    }
+    else if ( count < 64 ) {
+        z1 = ( a0<<negCount ) | ( a1 != 0 );
+        z0 = a0>>count;
+    }
+    else {
+        if ( count == 64 ) {
+            z1 = a0 | ( a1 != 0 );
+        }
+        else {
+            z1 = ( ( a0 | a1 ) != 0 );
+        }
+        z0 = 0;
+    }
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'.  Any bits shifted off are lost.  The value
+of `count' can be arbitrarily large; in particular, if `count' is greater
+than 128, the result will be 0.  The result is broken into two 64-bit pieces
+which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128Right(
+     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+    bits64 z0, z1;
+    int8 negCount = ( - count ) & 63;
+
+    if ( count == 0 ) {
+        z1 = a1;
+        z0 = a0;
+    }
+    else if ( count < 64 ) {
+        z1 = ( a0<<negCount ) | ( a1>>count );
+        z0 = a0>>count;
+    }
+    else {
+        z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
+        z0 = 0;
+    }
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'.  If any nonzero bits are shifted off, they
+are ``jammed'' into the least significant bit of the result by setting the
+least significant bit to 1.  The value of `count' can be arbitrarily large;
+in particular, if `count' is greater than 128, the result will be either
+0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
+nonzero.  The result is broken into two 64-bit pieces which are stored at
+the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128RightJamming(
+     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+    bits64 z0, z1;
+    int8 negCount = ( - count ) & 63;
+
+    if ( count == 0 ) {
+        z1 = a1;
+        z0 = a0;
+    }
+    else if ( count < 64 ) {
+        z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
+        z0 = a0>>count;
+    }
+    else {
+        if ( count == 64 ) {
+            z1 = a0 | ( a1 != 0 );
+        }
+        else if ( count < 128 ) {
+            z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
+        }
+        else {
+            z1 = ( ( a0 | a1 ) != 0 );
+        }
+        z0 = 0;
+    }
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
+by 64 _plus_ the number of bits given in `count'.  The shifted result is
+at most 128 nonzero bits; these are broken into two 64-bit pieces which are
+stored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted
+off form a third 64-bit result as follows:  The _last_ bit shifted off is
+the most-significant bit of the extra result, and the other 63 bits of the
+extra result are all zero if and only if _all_but_the_last_ bits shifted off
+were all zero.  This extra result is stored in the location pointed to by
+`z2Ptr'.  The value of `count' can be arbitrarily large.
+    (This routine makes more sense if `a0', `a1', and `a2' are considered
+to form a fixed-point value with binary point between `a1' and `a2'.  This
+fixed-point value is shifted right by the number of bits given in `count',
+and the integer part of the result is returned at the locations pointed to
+by `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly
+corrupted as described above, and is returned at the location pointed to by
+`z2Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128ExtraRightJamming(
+     bits64 a0,
+     bits64 a1,
+     bits64 a2,
+     int16 count,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr
+ )
+{
+    bits64 z0, z1, z2;
+    int8 negCount = ( - count ) & 63;
+
+    if ( count == 0 ) {
+        z2 = a2;
+        z1 = a1;
+        z0 = a0;
+    }
+    else {
+        if ( count < 64 ) {
+            z2 = a1<<negCount;
+            z1 = ( a0<<negCount ) | ( a1>>count );
+            z0 = a0>>count;
+        }
+        else {
+            if ( count == 64 ) {
+                z2 = a1;
+                z1 = a0;
+            }
+            else {
+                a2 |= a1;
+                if ( count < 128 ) {
+                    z2 = a0<<negCount;
+                    z1 = a0>>( count & 63 );
+                }
+                else {
+                    z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
+                    z1 = 0;
+                }
+            }
+            z0 = 0;
+        }
+        z2 |= ( a2 != 0 );
+    }
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
+number of bits given in `count'.  Any bits shifted off are lost.  The value
+of `count' must be less than 64.  The result is broken into two 64-bit
+pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift128Left(
+     bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+
+    *z1Ptr = a1<<count;
+    *z0Ptr =
+        ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
+by the number of bits given in `count'.  Any bits shifted off are lost.
+The value of `count' must be less than 64.  The result is broken into three
+64-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift192Left(
+     bits64 a0,
+     bits64 a1,
+     bits64 a2,
+     int16 count,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr
+ )
+{
+    bits64 z0, z1, z2;
+    int8 negCount;
+
+    z2 = a2<<count;
+    z1 = a1<<count;
+    z0 = a0<<count;
+    if ( 0 < count ) {
+        negCount = ( ( - count ) & 63 );
+        z1 |= a2>>negCount;
+        z0 |= a1>>negCount;
+    }
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
+value formed by concatenating `b0' and `b1'.  Addition is modulo 2^128, so
+any carry out is lost.  The result is broken into two 64-bit pieces which
+are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add128(
+     bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+    bits64 z1;
+
+    z1 = a1 + b1;
+    *z1Ptr = z1;
+    *z0Ptr = a0 + b0 + ( z1 < a1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
+192-bit value formed by concatenating `b0', `b1', and `b2'.  Addition is
+modulo 2^192, so any carry out is lost.  The result is broken into three
+64-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add192(
+     bits64 a0,
+     bits64 a1,
+     bits64 a2,
+     bits64 b0,
+     bits64 b1,
+     bits64 b2,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr
+ )
+{
+    bits64 z0, z1, z2;
+    int8 carry0, carry1;
+
+    z2 = a2 + b2;
+    carry1 = ( z2 < a2 );
+    z1 = a1 + b1;
+    carry0 = ( z1 < a1 );
+    z0 = a0 + b0;
+    z1 += carry1;
+    z0 += ( z1 < carry1 );
+    z0 += carry0;
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
+128-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo
+2^128, so any borrow out (carry out) is lost.  The result is broken into two
+64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
+`z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub128(
+     bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+
+    *z1Ptr = a1 - b1;
+    *z0Ptr = a0 - b0 - ( a1 < b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
+from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
+Subtraction is modulo 2^192, so any borrow out (carry out) is lost.  The
+result is broken into three 64-bit pieces which are stored at the locations
+pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub192(
+     bits64 a0,
+     bits64 a1,
+     bits64 a2,
+     bits64 b0,
+     bits64 b1,
+     bits64 b2,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr
+ )
+{
+    bits64 z0, z1, z2;
+    int8 borrow0, borrow1;
+
+    z2 = a2 - b2;
+    borrow1 = ( a2 < b2 );
+    z1 = a1 - b1;
+    borrow0 = ( a1 < b1 );
+    z0 = a0 - b0;
+    z0 -= ( z1 < borrow1 );
+    z1 -= borrow1;
+    z0 -= borrow0;
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies `a' by `b' to obtain a 128-bit product.  The product is broken
+into two 64-bit pieces which are stored at the locations pointed to by
+`z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+    bits32 aHigh, aLow, bHigh, bLow;
+    bits64 z0, zMiddleA, zMiddleB, z1;
+
+    aLow = a;
+    aHigh = a>>32;
+    bLow = b;
+    bHigh = b>>32;
+    z1 = ( (bits64) aLow ) * bLow;
+    zMiddleA = ( (bits64) aLow ) * bHigh;
+    zMiddleB = ( (bits64) aHigh ) * bLow;
+    z0 = ( (bits64) aHigh ) * bHigh;
+    zMiddleA += zMiddleB;
+    z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
+    zMiddleA <<= 32;
+    z1 += zMiddleA;
+    z0 += ( z1 < zMiddleA );
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
+`b' to obtain a 192-bit product.  The product is broken into three 64-bit
+pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
+`z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul128By64To192(
+     bits64 a0,
+     bits64 a1,
+     bits64 b,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr
+ )
+{
+    bits64 z0, z1, z2, more1;
+
+    mul64To128( a1, b, &z1, &z2 );
+    mul64To128( a0, b, &z0, &more1 );
+    add128( z0, more1, 0, z1, &z0, &z1 );
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
+128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
+product.  The product is broken into four 64-bit pieces which are stored at
+the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul128To256(
+     bits64 a0,
+     bits64 a1,
+     bits64 b0,
+     bits64 b1,
+     bits64 *z0Ptr,
+     bits64 *z1Ptr,
+     bits64 *z2Ptr,
+     bits64 *z3Ptr
+ )
+{
+    bits64 z0, z1, z2, z3;
+    bits64 more1, more2;
+
+    mul64To128( a1, b1, &z2, &z3 );
+    mul64To128( a1, b0, &z1, &more2 );
+    add128( z1, more2, 0, z2, &z1, &z2 );
+    mul64To128( a0, b0, &z0, &more1 );
+    add128( z0, more1, 0, z1, &z0, &z1 );
+    mul64To128( a0, b1, &more1, &more2 );
+    add128( more1, more2, 0, z2, &more1, &z2 );
+    add128( z0, z1, 0, more1, &z0, &z1 );
+    *z3Ptr = z3;
+    *z2Ptr = z2;
+    *z1Ptr = z1;
+    *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the 64-bit integer quotient obtained by dividing
+`b' into the 128-bit value formed by concatenating `a0' and `a1'.  The
+divisor `b' must be at least 2^63.  If q is the exact quotient truncated
+toward zero, the approximation returned lies between q and q + 2 inclusive.
+If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
+unsigned integer is returned.
+-------------------------------------------------------------------------------
+*/
+static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
+{
+    bits64 b0, b1;
+    bits64 rem0, rem1, term0, term1;
+    bits64 z;
+
+    if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
+    b0 = b>>32;
+    z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
+    mul64To128( b, z, &term0, &term1 );
+    sub128( a0, a1, term0, term1, &rem0, &rem1 );
+    while ( ( (sbits64) rem0 ) < 0 ) {
+        z -= LIT64( 0x100000000 );
+        b1 = b<<32;
+        add128( rem0, rem1, b0, b1, &rem0, &rem1 );
+    }
+    rem0 = ( rem0<<32 ) | ( rem1>>32 );
+    z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
+    return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not used */
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the square root of the 32-bit significand given
+by `a'.  Considered as an integer, `a' must be at least 2^31.  If bit 0 of
+`aExp' (the least significant bit) is 1, the integer returned approximates
+2^31*sqrt(`a'/2^31), where `a' is considered an integer.  If bit 0 of `aExp'
+is 0, the integer returned approximates 2^31*sqrt(`a'/2^30).  In either
+case, the approximation returned lies strictly within +/-2 of the exact
+value.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateSqrt32( int16 aExp, bits32 a )
+{
+    static const bits16 sqrtOddAdjustments[] = {
+        0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
+        0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
+    };
+    static const bits16 sqrtEvenAdjustments[] = {
+        0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
+        0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
+    };
+    int8 index;
+    bits32 z;
+
+    index = ( a>>27 ) & 15;
+    if ( aExp & 1 ) {
+        z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
+        z = ( ( a / z )<<14 ) + ( z<<15 );
+        a >>= 1;
+    }
+    else {
+        z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
+        z = a / z + z;
+        z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
+        if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
+    }
+    return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the number of leading 0 bits before the most-significant 1 bit of
+`a'.  If `a' is zero, 32 is returned.
+-------------------------------------------------------------------------------
+*/
+static int8 countLeadingZeros32( bits32 a )
+{
+    static const int8 countLeadingZerosHigh[] = {
+        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    int8 shiftCount;
+
+    shiftCount = 0;
+    if ( a < 0x10000 ) {
+        shiftCount += 16;
+        a <<= 16;
+    }
+    if ( a < 0x1000000 ) {
+        shiftCount += 8;
+        a <<= 8;
+    }
+    shiftCount += countLeadingZerosHigh[ a>>24 ];
+    return shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the number of leading 0 bits before the most-significant 1 bit of
+`a'.  If `a' is zero, 64 is returned.
+-------------------------------------------------------------------------------
+*/
+static int8 countLeadingZeros64( bits64 a )
+{
+    int8 shiftCount;
+
+    shiftCount = 0;
+    if ( a < ( (bits64) 1 )<<32 ) {
+        shiftCount += 32;
+    }
+    else {
+        a >>= 32;
+    }
+    shiftCount += countLeadingZeros32( a );
+    return shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
+is equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+    return ( a0 == b0 ) && ( a1 == b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+    return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+than the 128-bit value formed by concatenating `b0' and `b1'.  Otherwise,
+returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+    return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
+not equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+    return ( a0 != b0 ) || ( a1 != b1 );
+
+}
+
diff --git a/sys/lib/libkern/softfloat-specialize.h b/sys/lib/libkern/softfloat-specialize.h
new file mode 100644 (file)
index 0000000..2efb8ff
--- /dev/null
@@ -0,0 +1,480 @@
+/* $NetBSD: softfloat-specialize.h,v 1.2 2008/04/28 20:24:06 martin Exp $ */
+
+/* This is a derivative work. */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ross Harvey.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser.  This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704.  Funding was partially provided by the
+National Science Foundation under grant MIP-9311980.  The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Underflow tininess-detection mode, statically initialized to default value.
+-------------------------------------------------------------------------------
+*/
+
+/* [ MP safe, does not change dynamically ] */
+int float_detect_tininess = float_tininess_after_rounding;
+
+/*
+-------------------------------------------------------------------------------
+Internal canonical NaN format.
+-------------------------------------------------------------------------------
+*/
+typedef struct {
+    flag sign;
+    bits64 high, low;
+} commonNaNT;
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated single-precision NaN.
+-------------------------------------------------------------------------------
+*/
+#define float32_default_nan 0xFFC00000
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+static flag float32_is_nan( float32 a )
+{
+
+    return ( 0xFF000000 < (bits32) ( a<<1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a signaling
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float32_is_signaling_nan( float32 a )
+{
+
+    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point NaN
+`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float32ToCommonNaN( float32 a )
+{
+    commonNaNT z;
+
+    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+    z.sign = a>>31;
+    z.low = 0;
+    z.high = ( (bits64) a )<<41;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the single-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float32 commonNaNToFloat32( commonNaNT a )
+{
+
+    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two single-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float32 propagateFloat32NaN( float32 a, float32 b )
+{
+    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+    aIsNaN = float32_is_nan( a );
+    aIsSignalingNaN = float32_is_signaling_nan( a );
+    bIsNaN = float32_is_nan( b );
+    bIsSignalingNaN = float32_is_signaling_nan( b );
+    a |= 0x00400000;
+    b |= 0x00400000;
+    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+    if ( aIsSignalingNaN ) {
+        if ( bIsSignalingNaN ) goto returnLargerSignificand;
+        return bIsNaN ? b : a;
+    }
+    else if ( aIsNaN ) {
+        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+        if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
+        if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
+        return ( a < b ) ? a : b;
+    }
+    else {
+        return b;
+    }
+
+}
+
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point NaN
+`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float64ToCommonNaN( float64 a )
+{
+    commonNaNT z;
+
+    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+    z.sign = a>>63;
+    z.low = 0;
+    z.high = a<<12;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the double-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float64 commonNaNToFloat64( commonNaNT a )
+{
+
+    return
+          ( ( (bits64) a.sign )<<63 )
+        | LIT64( 0x7FF8000000000000 )
+        | ( a.high>>12 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two double-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float64 propagateFloat64NaN( float64 a, float64 b )
+{
+    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+    aIsNaN = float64_is_nan( a );
+    aIsSignalingNaN = float64_is_signaling_nan( a );
+    bIsNaN = float64_is_nan( b );
+    bIsSignalingNaN = float64_is_signaling_nan( b );
+    a |= LIT64( 0x0008000000000000 );
+    b |= LIT64( 0x0008000000000000 );
+    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+    if ( aIsSignalingNaN ) {
+        if ( bIsSignalingNaN ) goto returnLargerSignificand;
+        return bIsNaN ? b : a;
+    }
+    else if ( aIsNaN ) {
+        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+        if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
+        if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
+        return ( a < b ) ? a : b;
+    }
+    else {
+        return b;
+    }
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated extended double-precision NaN.  The
+`high' and `low' values hold the most- and least-significant bits,
+respectively.
+-------------------------------------------------------------------------------
+*/
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+static flag floatx80_is_nan( floatx80 a )
+{
+
+    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_is_signaling_nan( floatx80 a )
+{
+    bits64 aLow;
+
+    aLow = a.low & ~ LIT64( 0x4000000000000000 );
+    return
+           ( ( a.high & 0x7FFF ) == 0x7FFF )
+        && (bits64) ( aLow<<1 )
+        && ( a.low == aLow );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
+invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT floatx80ToCommonNaN( floatx80 a )
+{
+    commonNaNT z;
+
+    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+    z.sign = a.high>>15;
+    z.low = 0;
+    z.high = a.low<<1;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the extended
+double-precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static floatx80 commonNaNToFloatx80( commonNaNT a )
+{
+    floatx80 z;
+
+    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two extended double-precision floating-point values `a' and `b', one
+of which is a NaN, and returns the appropriate NaN result.  If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
+{
+    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+    aIsNaN = floatx80_is_nan( a );
+    aIsSignalingNaN = floatx80_is_signaling_nan( a );
+    bIsNaN = floatx80_is_nan( b );
+    bIsSignalingNaN = floatx80_is_signaling_nan( b );
+    a.low |= LIT64( 0xC000000000000000 );
+    b.low |= LIT64( 0xC000000000000000 );
+    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+    if ( aIsSignalingNaN ) {
+        if ( bIsSignalingNaN ) goto returnLargerSignificand;
+        return bIsNaN ? b : a;
+    }
+    else if ( aIsNaN ) {
+        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+        if ( a.low < b.low ) return b;
+        if ( b.low < a.low ) return a;
+        return ( a.high < b.high ) ? a : b;
+    }
+    else {
+        return b;
+    }
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated quadruple-precision NaN.  The `high' and
+`low' values hold the most- and least-significant bits, respectively.
+-------------------------------------------------------------------------------
+*/
+#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
+#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_nan( float128 a )
+{
+
+    return
+           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
+        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_signaling_nan( float128 a )
+{
+
+    return
+           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
+        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point NaN
+`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float128ToCommonNaN( float128 a )
+{
+    commonNaNT z;
+
+    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+    z.sign = a.high>>63;
+    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the quadruple-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float128 commonNaNToFloat128( commonNaNT a )
+{
+    float128 z;
+
+    shift128Right( a.high, a.low, 16, &z.high, &z.low );
+    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two quadruple-precision floating-point values `a' and `b', one of
+which is a NaN, and returns the appropriate NaN result.  If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float128 propagateFloat128NaN( float128 a, float128 b )
+{
+    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+    aIsNaN = float128_is_nan( a );
+    aIsSignalingNaN = float128_is_signaling_nan( a );
+    bIsNaN = float128_is_nan( b );
+    bIsSignalingNaN = float128_is_signaling_nan( b );
+    a.high |= LIT64( 0x0000800000000000 );
+    b.high |= LIT64( 0x0000800000000000 );
+    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+    if ( aIsSignalingNaN ) {
+        if ( bIsSignalingNaN ) goto returnLargerSignificand;
+        return bIsNaN ? b : a;
+    }
+    else if ( aIsNaN ) {
+        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
+        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
+        return ( a.high < b.high ) ? a : b;
+    }
+    else {
+        return b;
+    }
+
+}
+
+#endif
+
diff --git a/sys/lib/libkern/softfloat.c b/sys/lib/libkern/softfloat.c
new file mode 100644 (file)
index 0000000..43f64f3
--- /dev/null
@@ -0,0 +1,5502 @@
+/* $NetBSD: softfloat.c,v 1.4 2005/12/11 12:24:37 christos Exp $ */
+
+/*
+ * This version hacked for use with gcc -msoft-float by bjh21.
+ * (Mostly a case of #ifdefing out things GCC doesn't need or provides
+ *  itself).
+ */
+
+/*
+ * Things you may want to define:
+ *
+ * SOFTFLOAT_FOR_GCC - build only those functions necessary for GCC (with
+ *   -msoft-float) to work.  Include "softfloat-for-gcc.h" to get them
+ *   properly renamed.
+ */
+
+/*
+===============================================================================
+
+This C source file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser.  This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704.  Funding was partially provided by the
+National Science Foundation under grant MIP-9311980.  The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/* If you need this in a boot program, you have bigger problems... */
+#ifndef _STANDALONE
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: softfloat.c,v 1.4 2005/12/11 12:24:37 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+
+#include "milieu.h"
+#include "softfloat.h"
+
+/*
+ * Conversions between floats as stored in memory and floats as
+ * SoftFloat uses them
+ */
+#ifndef FLOAT64_DEMANGLE
+#define FLOAT64_DEMANGLE(a)    (a)
+#endif
+#ifndef FLOAT64_MANGLE
+#define FLOAT64_MANGLE(a)      (a)
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Floating-point rounding mode, extended double-precision rounding precision,
+and exception flags.
+-------------------------------------------------------------------------------
+*/
+
+/*
+ * XXX: This may cause options-MULTIPROCESSOR or thread problems someday.
+ *     Right now, it does not.  I've removed all other dynamic global
+ *     variables. [ross]
+ */
+#ifdef FLOATX80
+int8 floatx80_rounding_precision = 80;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Primitive arithmetic functions, including multi-word arithmetic, and
+division and square root approximations.  (Can be specialized to target if
+desired.)
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-macros.h"
+
+/*
+-------------------------------------------------------------------------------
+Functions and definitions to determine:  (1) whether tininess for underflow
+is detected before or after rounding by default, (2) what (if anything)
+happens when exceptions are raised, (3) how signaling NaNs are distinguished
+from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
+are propagated from function inputs to output.  These details are target-
+specific.
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-specialize.h"
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not used */
+/*
+-------------------------------------------------------------------------------
+Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
+and 7, and returns the properly rounded 32-bit integer corresponding to the
+input.  If `zSign' is 1, the input is negated before being converted to an
+integer.  Bit 63 of `absZ' must be zero.  Ordinarily, the fixed-point input
+is simply rounded to an integer, with the inexact exception raised if the
+input cannot be represented exactly as an integer.  However, if the fixed-
+point input is too large, the invalid exception is raised and the largest
+positive or negative integer is returned.
+-------------------------------------------------------------------------------
+*/
+static int32 roundAndPackInt32( flag zSign, bits64 absZ )
+{
+    int8 roundingMode;
+    flag roundNearestEven;
+    int8 roundIncrement, roundBits;
+    int32 z;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    roundIncrement = 0x40;
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = 0x7F;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = absZ & 0x7F;
+    absZ = ( absZ + roundIncrement )>>7;
+    absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+    z = absZ;
+    if ( zSign ) z = - z;
+    if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
+        float_raise( float_flag_invalid );
+        return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+    }
+    if ( roundBits ) float_set_inexact();
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
+`absZ1', with binary point between bits 63 and 64 (between the input words),
+and returns the properly rounded 64-bit integer corresponding to the input.
+If `zSign' is 1, the input is negated before being converted to an integer.
+Ordinarily, the fixed-point input is simply rounded to an integer, with
+the inexact exception raised if the input cannot be represented exactly as
+an integer.  However, if the fixed-point input is too large, the invalid
+exception is raised and the largest positive or negative integer is
+returned.
+-------------------------------------------------------------------------------
+*/
+static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 )
+{
+    int8 roundingMode;
+    flag roundNearestEven, increment;
+    int64 z;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    increment = ( (sbits64) absZ1 < 0 );
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            increment = 0;
+        }
+        else {
+            if ( zSign ) {
+                increment = ( roundingMode == float_round_down ) && absZ1;
+            }
+            else {
+                increment = ( roundingMode == float_round_up ) && absZ1;
+            }
+        }
+    }
+    if ( increment ) {
+        ++absZ0;
+        if ( absZ0 == 0 ) goto overflow;
+        absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
+    }
+    z = absZ0;
+    if ( zSign ) z = - z;
+    if ( z && ( ( z < 0 ) ^ zSign ) ) {
+ overflow:
+        float_raise( float_flag_invalid );
+        return
+              zSign ? (sbits64) LIT64( 0x8000000000000000 )
+            : LIT64( 0x7FFFFFFFFFFFFFFF );
+    }
+    if ( absZ1 ) float_set_inexact();
+    return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits32 extractFloat32Frac( float32 a )
+{
+
+    return a & 0x007FFFFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat32Exp( float32 a )
+{
+
+    return ( a>>23 ) & 0xFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat32Sign( float32 a )
+{
+
+    return a>>31;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal single-precision floating-point value represented
+by the denormalized significand `aSig'.  The normalized exponent and
+significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
+{
+    int8 shiftCount;
+
+    shiftCount = countLeadingZeros32( aSig ) - 8;
+    *zSigPtr = aSig<<shiftCount;
+    *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+single-precision floating-point value, returning the result.  After being
+shifted into the proper positions, the three fields are simply added
+together to form the result.  This means that any integer portion of `zSig'
+will be added into the exponent.  Since a properly normalized significand
+will have an integer portion equal to 1, the `zExp' input should be 1 less
+than the desired result exponent whenever `zSig' is a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+
+    return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input.  Ordinarily, the abstract
+value is simply rounded and packed into the single-precision format, with
+the inexact exception raised if the abstract input cannot be represented
+exactly.  However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned.  If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal single-
+precision floating-point number.
+    The input significand `zSig' has its binary point between bits 30
+and 29, which is 7 bits to the left of the usual location.  This shifted
+significand must be normalized or smaller.  If `zSig' is not normalized,
+`zExp' must be 0; in that case, the result returned is a subnormal number,
+and it must not require rounding.  In the usual case that `zSig' is
+normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+The handling of underflow and overflow follows the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+    int8 roundingMode;
+    flag roundNearestEven;
+    int8 roundIncrement, roundBits;
+    flag isTiny;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    roundIncrement = 0x40;
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = 0x7F;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = zSig & 0x7F;
+    if ( 0xFD <= (bits16) zExp ) {
+        if (    ( 0xFD < zExp )
+             || (    ( zExp == 0xFD )
+                  && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
+           ) {
+            float_raise( float_flag_overflow | float_flag_inexact );
+            return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
+        }
+        if ( zExp < 0 ) {
+            isTiny =
+                   ( float_detect_tininess == float_tininess_before_rounding )
+                || ( zExp < -1 )
+                || ( zSig + roundIncrement < 0x80000000 );
+            shift32RightJamming( zSig, - zExp, &zSig );
+            zExp = 0;
+            roundBits = zSig & 0x7F;
+            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+        }
+    }
+    if ( roundBits ) float_set_inexact();
+    zSig = ( zSig + roundIncrement )>>7;
+    zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+    if ( zSig == 0 ) zExp = 0;
+    return packFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input.  This routine is just like
+`roundAndPackFloat32' except that `zSig' does not have to be normalized.
+Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
+floating-point exponent.
+-------------------------------------------------------------------------------
+*/
+static float32
+ normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+    int8 shiftCount;
+
+    shiftCount = countLeadingZeros32( zSig ) - 1;
+    return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat64Frac( float64 a )
+{
+
+    return FLOAT64_DEMANGLE(a) & LIT64( 0x000FFFFFFFFFFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat64Exp( float64 a )
+{
+
+    return ( FLOAT64_DEMANGLE(a)>>52 ) & 0x7FF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat64Sign( float64 a )
+{
+
+    return FLOAT64_DEMANGLE(a)>>63;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal double-precision floating-point value represented
+by the denormalized significand `aSig'.  The normalized exponent and
+significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
+{
+    int8 shiftCount;
+
+    shiftCount = countLeadingZeros64( aSig ) - 11;
+    *zSigPtr = aSig<<shiftCount;
+    *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+double-precision floating-point value, returning the result.  After being
+shifted into the proper positions, the three fields are simply added
+together to form the result.  This means that any integer portion of `zSig'
+will be added into the exponent.  Since a properly normalized significand
+will have an integer portion equal to 1, the `zExp' input should be 1 less
+than the desired result exponent whenever `zSig' is a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+
+    return FLOAT64_MANGLE( ( ( (bits64) zSign )<<63 ) +
+                          ( ( (bits64) zExp )<<52 ) + zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper double-precision floating-
+point value corresponding to the abstract input.  Ordinarily, the abstract
+value is simply rounded and packed into the double-precision format, with
+the inexact exception raised if the abstract input cannot be represented
+exactly.  However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned.  If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal double-
+precision floating-point number.
+    The input significand `zSig' has its binary point between bits 62
+and 61, which is 10 bits to the left of the usual location.  This shifted
+significand must be normalized or smaller.  If `zSig' is not normalized,
+`zExp' must be 0; in that case, the result returned is a subnormal number,
+and it must not require rounding.  In the usual case that `zSig' is
+normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+The handling of underflow and overflow follows the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+    int8 roundingMode;
+    flag roundNearestEven;
+    int16 roundIncrement, roundBits;
+    flag isTiny;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    roundIncrement = 0x200;
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = 0x3FF;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = zSig & 0x3FF;
+    if ( 0x7FD <= (bits16) zExp ) {
+        if (    ( 0x7FD < zExp )
+             || (    ( zExp == 0x7FD )
+                  && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
+           ) {
+            float_raise( float_flag_overflow | float_flag_inexact );
+            return FLOAT64_MANGLE(
+               FLOAT64_DEMANGLE(packFloat64( zSign, 0x7FF, 0 )) -
+               ( roundIncrement == 0 ));
+        }
+        if ( zExp < 0 ) {
+            isTiny =
+                   ( float_detect_tininess == float_tininess_before_rounding )
+                || ( zExp < -1 )
+                || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
+            shift64RightJamming( zSig, - zExp, &zSig );
+            zExp = 0;
+            roundBits = zSig & 0x3FF;
+            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+        }
+    }
+    if ( roundBits ) float_set_inexact();
+    zSig = ( zSig + roundIncrement )>>10;
+    zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
+    if ( zSig == 0 ) zExp = 0;
+    return packFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper double-precision floating-
+point value corresponding to the abstract input.  This routine is just like
+`roundAndPackFloat64' except that `zSig' does not have to be normalized.
+Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
+floating-point exponent.
+-------------------------------------------------------------------------------
+*/
+static float64
+ normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+    int8 shiftCount;
+
+    shiftCount = countLeadingZeros64( zSig ) - 1;
+    return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the extended double-precision floating-point
+value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloatx80Frac( floatx80 a )
+{
+
+    return a.low;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the extended double-precision floating-point
+value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int32 extractFloatx80Exp( floatx80 a )
+{
+
+    return a.high & 0x7FFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the extended double-precision floating-point value
+`a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloatx80Sign( floatx80 a )
+{
+
+    return a.high>>15;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal extended double-precision floating-point value
+represented by the denormalized significand `aSig'.  The normalized exponent
+and significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
+{
+    int8 shiftCount;
+
+    shiftCount = countLeadingZeros64( aSig );
+    *zSigPtr = aSig<<shiftCount;
+    *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
+extended double-precision floating-point value, returning the result.
+-------------------------------------------------------------------------------
+*/
+INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
+{
+    floatx80 z;
+
+    z.low = zSig;
+    z.high = ( ( (bits16) zSign )<<15 ) + zExp;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and extended significand formed by the concatenation of `zSig0' and `zSig1',
+and returns the proper extended double-precision floating-point value
+corresponding to the abstract input.  Ordinarily, the abstract value is
+rounded and packed into the extended double-precision format, with the
+inexact exception raised if the abstract input cannot be represented
+exactly.  However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned.  If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal extended
+double-precision floating-point number.
+    If `roundingPrecision' is 32 or 64, the result is rounded to the same
+number of bits as single or double precision, respectively.  Otherwise, the
+result is rounded to the full precision of the extended double-precision
+format.
+    The input significand must be normalized or smaller.  If the input
+significand is not normalized, `zExp' must be 0; in that case, the result
+returned is a subnormal number, and it must not require rounding.  The
+handling of underflow and overflow follows the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80
+ roundAndPackFloatx80(
+     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+ )
+{
+    int8 roundingMode;
+    flag roundNearestEven, increment, isTiny;
+    int64 roundIncrement, roundMask, roundBits;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    if ( roundingPrecision == 80 ) goto precision80;
+    if ( roundingPrecision == 64 ) {
+        roundIncrement = LIT64( 0x0000000000000400 );
+        roundMask = LIT64( 0x00000000000007FF );
+    }
+    else if ( roundingPrecision == 32 ) {
+        roundIncrement = LIT64( 0x0000008000000000 );
+        roundMask = LIT64( 0x000000FFFFFFFFFF );
+    }
+    else {
+        goto precision80;
+    }
+    zSig0 |= ( zSig1 != 0 );
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            roundIncrement = 0;
+        }
+        else {
+            roundIncrement = roundMask;
+            if ( zSign ) {
+                if ( roundingMode == float_round_up ) roundIncrement = 0;
+            }
+            else {
+                if ( roundingMode == float_round_down ) roundIncrement = 0;
+            }
+        }
+    }
+    roundBits = zSig0 & roundMask;
+    if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+        if (    ( 0x7FFE < zExp )
+             || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
+           ) {
+            goto overflow;
+        }
+        if ( zExp <= 0 ) {
+            isTiny =
+                   ( float_detect_tininess == float_tininess_before_rounding )
+                || ( zExp < 0 )
+                || ( zSig0 <= zSig0 + roundIncrement );
+            shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
+            zExp = 0;
+            roundBits = zSig0 & roundMask;
+            if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+            if ( roundBits ) float_set_inexact();
+            zSig0 += roundIncrement;
+            if ( (sbits64) zSig0 < 0 ) zExp = 1;
+            roundIncrement = roundMask + 1;
+            if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+                roundMask |= roundIncrement;
+            }
+            zSig0 &= ~ roundMask;
+            return packFloatx80( zSign, zExp, zSig0 );
+        }
+    }
+    if ( roundBits ) float_set_inexact();
+    zSig0 += roundIncrement;
+    if ( zSig0 < roundIncrement ) {
+        ++zExp;
+        zSig0 = LIT64( 0x8000000000000000 );
+    }
+    roundIncrement = roundMask + 1;
+    if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+        roundMask |= roundIncrement;
+    }
+    zSig0 &= ~ roundMask;
+    if ( zSig0 == 0 ) zExp = 0;
+    return packFloatx80( zSign, zExp, zSig0 );
+ precision80:
+    increment = ( (sbits64) zSig1 < 0 );
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            increment = 0;
+        }
+        else {
+            if ( zSign ) {
+                increment = ( roundingMode == float_round_down ) && zSig1;
+            }
+            else {
+                increment = ( roundingMode == float_round_up ) && zSig1;
+            }
+        }
+    }
+    if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+        if (    ( 0x7FFE < zExp )
+             || (    ( zExp == 0x7FFE )
+                  && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
+                  && increment
+                )
+           ) {
+            roundMask = 0;
+ overflow:
+            float_raise( float_flag_overflow | float_flag_inexact );
+            if (    ( roundingMode == float_round_to_zero )
+                 || ( zSign && ( roundingMode == float_round_up ) )
+                 || ( ! zSign && ( roundingMode == float_round_down ) )
+               ) {
+                return packFloatx80( zSign, 0x7FFE, ~ roundMask );
+            }
+            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        }
+        if ( zExp <= 0 ) {
+            isTiny =
+                   ( float_detect_tininess == float_tininess_before_rounding )
+                || ( zExp < 0 )
+                || ! increment
+                || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
+            shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
+            zExp = 0;
+            if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
+            if ( zSig1 ) float_set_inexact();
+            if ( roundNearestEven ) {
+                increment = ( (sbits64) zSig1 < 0 );
+            }
+            else {
+                if ( zSign ) {
+                    increment = ( roundingMode == float_round_down ) && zSig1;
+                }
+                else {
+                    increment = ( roundingMode == float_round_up ) && zSig1;
+                }
+            }
+            if ( increment ) {
+                ++zSig0;
+                zSig0 &=
+                    ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+                if ( (sbits64) zSig0 < 0 ) zExp = 1;
+            }
+            return packFloatx80( zSign, zExp, zSig0 );
+        }
+    }
+    if ( zSig1 ) float_set_inexact();
+    if ( increment ) {
+        ++zSig0;
+        if ( zSig0 == 0 ) {
+            ++zExp;
+            zSig0 = LIT64( 0x8000000000000000 );
+        }
+        else {
+            zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+        }
+    }
+    else {
+        if ( zSig0 == 0 ) zExp = 0;
+    }
+    return packFloatx80( zSign, zExp, zSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent
+`zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
+and returns the proper extended double-precision floating-point value
+corresponding to the abstract input.  This routine is just like
+`roundAndPackFloatx80' except that the input significand does not have to be
+normalized.
+-------------------------------------------------------------------------------
+*/
+static floatx80
+ normalizeRoundAndPackFloatx80(
+     int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+ )
+{
+    int8 shiftCount;
+
+    if ( zSig0 == 0 ) {
+        zSig0 = zSig1;
+        zSig1 = 0;
+        zExp -= 64;
+    }
+    shiftCount = countLeadingZeros64( zSig0 );
+    shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+    zExp -= shiftCount;
+    return
+        roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the least-significant 64 fraction bits of the quadruple-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat128Frac1( float128 a )
+{
+
+    return a.low;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the most-significant 48 fraction bits of the quadruple-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat128Frac0( float128 a )
+{
+
+    return a.high & LIT64( 0x0000FFFFFFFFFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the quadruple-precision floating-point value
+`a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int32 extractFloat128Exp( float128 a )
+{
+
+    return ( a.high>>48 ) & 0x7FFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the quadruple-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat128Sign( float128 a )
+{
+
+    return a.high>>63;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal quadruple-precision floating-point value
+represented by the denormalized significand formed by the concatenation of
+`aSig0' and `aSig1'.  The normalized exponent is stored at the location
+pointed to by `zExpPtr'.  The most significant 49 bits of the normalized
+significand are stored at the location pointed to by `zSig0Ptr', and the
+least significant 64 bits of the normalized significand are stored at the
+location pointed to by `zSig1Ptr'.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat128Subnormal(
+     bits64 aSig0,
+     bits64 aSig1,
+     int32 *zExpPtr,
+     bits64 *zSig0Ptr,
+     bits64 *zSig1Ptr
+ )
+{
+    int8 shiftCount;
+
+    if ( aSig0 == 0 ) {
+        shiftCount = countLeadingZeros64( aSig1 ) - 15;
+        if ( shiftCount < 0 ) {
+            *zSig0Ptr = aSig1>>( - shiftCount );
+            *zSig1Ptr = aSig1<<( shiftCount & 63 );
+        }
+        else {
+            *zSig0Ptr = aSig1<<shiftCount;
+            *zSig1Ptr = 0;
+        }
+        *zExpPtr = - shiftCount - 63;
+    }
+    else {
+        shiftCount = countLeadingZeros64( aSig0 ) - 15;
+        shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
+        *zExpPtr = 1 - shiftCount;
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', the exponent `zExp', and the significand formed
+by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
+floating-point value, returning the result.  After being shifted into the
+proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
+added together to form the most significant 32 bits of the result.  This
+means that any integer portion of `zSig0' will be added into the exponent.
+Since a properly normalized significand will have an integer portion equal
+to 1, the `zExp' input should be 1 less than the desired result exponent
+whenever `zSig0' and `zSig1' concatenated form a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float128
+ packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
+{
+    float128 z;
+
+    z.low = zSig1;
+    z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and extended significand formed by the concatenation of `zSig0', `zSig1',
+and `zSig2', and returns the proper quadruple-precision floating-point value
+corresponding to the abstract input.  Ordinarily, the abstract value is
+simply rounded and packed into the quadruple-precision format, with the
+inexact exception raised if the abstract input cannot be represented
+exactly.  However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned.  If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal quadruple-
+precision floating-point number.
+    The input significand must be normalized or smaller.  If the input
+significand is not normalized, `zExp' must be 0; in that case, the result
+returned is a subnormal number, and it must not require rounding.  In the
+usual case that the input significand is normalized, `zExp' must be 1 less
+than the ``true'' floating-point exponent.  The handling of underflow and
+overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128
+ roundAndPackFloat128(
+     flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 )
+{
+    int8 roundingMode;
+    flag roundNearestEven, increment, isTiny;
+
+    roundingMode = float_rounding_mode();
+    roundNearestEven = ( roundingMode == float_round_nearest_even );
+    increment = ( (sbits64) zSig2 < 0 );
+    if ( ! roundNearestEven ) {
+        if ( roundingMode == float_round_to_zero ) {
+            increment = 0;
+        }
+        else {
+            if ( zSign ) {
+                increment = ( roundingMode == float_round_down ) && zSig2;
+            }
+            else {
+                increment = ( roundingMode == float_round_up ) && zSig2;
+            }
+        }
+    }
+    if ( 0x7FFD <= (bits32) zExp ) {
+        if (    ( 0x7FFD < zExp )
+             || (    ( zExp == 0x7FFD )
+                  && eq128(
+                         LIT64( 0x0001FFFFFFFFFFFF ),
+                         LIT64( 0xFFFFFFFFFFFFFFFF ),
+                         zSig0,
+                         zSig1
+                     )
+                  && increment
+                )
+           ) {
+            float_raise( float_flag_overflow | float_flag_inexact );
+            if (    ( roundingMode == float_round_to_zero )
+                 || ( zSign && ( roundingMode == float_round_up ) )
+                 || ( ! zSign && ( roundingMode == float_round_down ) )
+               ) {
+                return
+                    packFloat128(
+                        zSign,
+                        0x7FFE,
+                        LIT64( 0x0000FFFFFFFFFFFF ),
+                        LIT64( 0xFFFFFFFFFFFFFFFF )
+                    );
+            }
+            return packFloat128( zSign, 0x7FFF, 0, 0 );
+        }
+        if ( zExp < 0 ) {
+            isTiny =
+                   ( float_detect_tininess == float_tininess_before_rounding )
+                || ( zExp < -1 )
+                || ! increment
+                || lt128(
+                       zSig0,
+                       zSig1,
+                       LIT64( 0x0001FFFFFFFFFFFF ),
+                       LIT64( 0xFFFFFFFFFFFFFFFF )
+                   );
+            shift128ExtraRightJamming(
+                zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
+            zExp = 0;
+            if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
+            if ( roundNearestEven ) {
+                increment = ( (sbits64) zSig2 < 0 );
+            }
+            else {
+                if ( zSign ) {
+                    increment = ( roundingMode == float_round_down ) && zSig2;
+                }
+                else {
+                    increment = ( roundingMode == float_round_up ) && zSig2;
+                }
+            }
+        }
+    }
+    if ( zSig2 ) float_set_inexact();
+    if ( increment ) {
+        add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
+        zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
+    }
+    else {
+        if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
+    }
+    return packFloat128( zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand formed by the concatenation of `zSig0' and `zSig1', and
+returns the proper quadruple-precision floating-point value corresponding
+to the abstract input.  This routine is just like `roundAndPackFloat128'
+except that the input significand has fewer bits and does not have to be
+normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
+point exponent.
+-------------------------------------------------------------------------------
+*/
+static float128
+ normalizeRoundAndPackFloat128(
+     flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
+{
+    int8 shiftCount;
+    bits64 zSig2;
+
+    if ( zSig0 == 0 ) {
+        zSig0 = zSig1;
+        zSig1 = 0;
+        zExp -= 64;
+    }
+    shiftCount = countLeadingZeros64( zSig0 ) - 15;
+    if ( 0 <= shiftCount ) {
+        zSig2 = 0;
+        shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+    }
+    else {
+        shift128ExtraRightJamming(
+            zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
+    }
+    zExp -= shiftCount;
+    return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the single-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int32 a )
+{
+    flag zSign;
+
+    if ( a == 0 ) return 0;
+    if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
+    zSign = ( a < 0 );
+    return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the double-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 int32_to_float64( int32 a )
+{
+    flag zSign;
+    uint32 absA;
+    int8 shiftCount;
+    bits64 zSig;
+
+    if ( a == 0 ) return 0;
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros32( absA ) + 21;
+    zSig = absA;
+    return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the extended double-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 int32_to_floatx80( int32 a )
+{
+    flag zSign;
+    uint32 absA;
+    int8 shiftCount;
+    bits64 zSig;
+
+    if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros32( absA ) + 32;
+    zSig = absA;
+    return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a' to
+the quadruple-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 int32_to_float128( int32 a )
+{
+    flag zSign;
+    uint32 absA;
+    int8 shiftCount;
+    bits64 zSig0;
+
+    if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros32( absA ) + 17;
+    zSig0 = absA;
+    return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the single-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 int64_to_float32( int64 a )
+{
+    flag zSign;
+    uint64 absA;
+    int8 shiftCount;
+
+    if ( a == 0 ) return 0;
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros64( absA ) - 40;
+    if ( 0 <= shiftCount ) {
+        return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );
+    }
+    else {
+        shiftCount += 7;
+        if ( shiftCount < 0 ) {
+            shift64RightJamming( absA, - shiftCount, &absA );
+        }
+        else {
+            absA <<= shiftCount;
+        }
+        return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the double-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 int64_to_float64( int64 a )
+{
+    flag zSign;
+
+    if ( a == 0 ) return 0;
+    if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
+        return packFloat64( 1, 0x43E, 0 );
+    }
+    zSign = ( a < 0 );
+    return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the extended double-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 int64_to_floatx80( int64 a )
+{
+    flag zSign;
+    uint64 absA;
+    int8 shiftCount;
+
+    if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros64( absA );
+    return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a' to
+the quadruple-precision floating-point format.  The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 int64_to_float128( int64 a )
+{
+    flag zSign;
+    uint64 absA;
+    int8 shiftCount;
+    int32 zExp;
+    bits64 zSig0, zSig1;
+
+    if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+    zSign = ( a < 0 );
+    absA = zSign ? - a : a;
+    shiftCount = countLeadingZeros64( absA ) + 49;
+    zExp = 0x406E - shiftCount;
+    if ( 64 <= shiftCount ) {
+        zSig1 = 0;
+        zSig0 = absA;
+        shiftCount -= 64;
+    }
+    else {
+        zSig1 = absA;
+        zSig0 = 0;
+    }
+    shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+    return packFloat128( zSign, zExp, zSig0, zSig1 );
+
+}
+
+#endif
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32( float32 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    bits64 aSig64;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    if ( ( aExp == 0xFF ) && aSig ) aSign = 0;
+    if ( aExp ) aSig |= 0x00800000;
+    shiftCount = 0xAF - aExp;
+    aSig64 = aSig;
+    aSig64 <<= 32;
+    if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 );
+    return roundAndPackInt32( aSign, aSig64 );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32_round_to_zero( float32 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    int32 z;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    shiftCount = aExp - 0x9E;
+    if ( 0 <= shiftCount ) {
+        if ( a != 0xCF000000 ) {
+            float_raise( float_flag_invalid );
+            if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
+        }
+        return (sbits32) 0x80000000;
+    }
+    else if ( aExp <= 0x7E ) {
+        if ( aExp | aSig ) float_set_inexact();
+        return 0;
+    }
+    aSig = ( aSig | 0x00800000 )<<8;
+    z = aSig>>( - shiftCount );
+    if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+        float_set_inexact();
+    }
+    if ( aSign ) z = - z;
+    return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 64-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float32_to_int64( float32 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    bits64 aSig64, aSigExtra;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    shiftCount = 0xBE - aExp;
+    if ( shiftCount < 0 ) {
+        float_raise( float_flag_invalid );
+        if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+            return LIT64( 0x7FFFFFFFFFFFFFFF );
+        }
+        return (sbits64) LIT64( 0x8000000000000000 );
+    }
+    if ( aExp ) aSig |= 0x00800000;
+    aSig64 = aSig;
+    aSig64 <<= 40;
+    shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra );
+    return roundAndPackInt64( aSign, aSig64, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 64-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.  If
+`a' is a NaN, the largest positive integer is returned.  Otherwise, if the
+conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float32_to_int64_round_to_zero( float32 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    bits64 aSig64;
+    int64 z;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    shiftCount = aExp - 0xBE;
+    if ( 0 <= shiftCount ) {
+        if ( a != 0xDF000000 ) {
+            float_raise( float_flag_invalid );
+            if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+                return LIT64( 0x7FFFFFFFFFFFFFFF );
+            }
+        }
+        return (sbits64) LIT64( 0x8000000000000000 );
+    }
+    else if ( aExp <= 0x7E ) {
+        if ( aExp | aSig ) float_set_inexact();
+        return 0;
+    }
+    aSig64 = aSig | 0x00800000;
+    aSig64 <<= 40;
+    z = aSig64>>( - shiftCount );
+    if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) {
+        float_set_inexact();
+    }
+    if ( aSign ) z = - z;
+    return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the double-precision floating-point format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float32_to_float64( float32 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits32 aSig;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
+        return packFloat64( aSign, 0x7FF, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+        --aExp;
+    }
+    return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the extended double-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float32_to_floatx80( float32 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits32 aSig;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) );
+        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+    }
+    aSig |= 0x00800000;
+    return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the double-precision floating-point format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float32_to_float128( float32 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits32 aSig;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) );
+        return packFloat128( aSign, 0x7FFF, 0, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+        --aExp;
+    }
+    return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Rounds the single-precision floating-point value `a' to an integer, and
+returns the result as a single-precision floating-point value.  The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits32 lastBitMask, roundBitsMask;
+    int8 roundingMode;
+    float32 z;
+
+    aExp = extractFloat32Exp( a );
+    if ( 0x96 <= aExp ) {
+        if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
+            return propagateFloat32NaN( a, a );
+        }
+        return a;
+    }
+    if ( aExp <= 0x7E ) {
+        if ( (bits32) ( a<<1 ) == 0 ) return a;
+        float_set_inexact();
+        aSign = extractFloat32Sign( a );
+        switch ( float_rounding_mode() ) {
+         case float_round_nearest_even:
+            if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
+                return packFloat32( aSign, 0x7F, 0 );
+            }
+            break;
+         case float_round_down:
+            return aSign ? 0xBF800000 : 0;
+         case float_round_up:
+            return aSign ? 0x80000000 : 0x3F800000;
+        }
+        return packFloat32( aSign, 0, 0 );
+    }
+    lastBitMask = 1;
+    lastBitMask <<= 0x96 - aExp;
+    roundBitsMask = lastBitMask - 1;
+    z = a;
+    roundingMode = float_rounding_mode();
+    if ( roundingMode == float_round_nearest_even ) {
+        z += lastBitMask>>1;
+        if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
+    }
+    else if ( roundingMode != float_round_to_zero ) {
+        if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+            z += roundBitsMask;
+        }
+    }
+    z &= ~ roundBitsMask;
+    if ( z != a ) float_set_inexact();
+    return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the single-precision
+floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
+before being returned.  `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+    int16 aExp, bExp, zExp;
+    bits32 aSig, bSig, zSig;
+    int16 expDiff;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    bSig = extractFloat32Frac( b );
+    bExp = extractFloat32Exp( b );
+    expDiff = aExp - bExp;
+    aSig <<= 6;
+    bSig <<= 6;
+    if ( 0 < expDiff ) {
+        if ( aExp == 0xFF ) {
+            if ( aSig ) return propagateFloat32NaN( a, b );
+            return a;
+        }
+        if ( bExp == 0 ) {
+            --expDiff;
+        }
+        else {
+            bSig |= 0x20000000;
+        }
+        shift32RightJamming( bSig, expDiff, &bSig );
+        zExp = aExp;
+    }
+    else if ( expDiff < 0 ) {
+        if ( bExp == 0xFF ) {
+            if ( bSig ) return propagateFloat32NaN( a, b );
+            return packFloat32( zSign, 0xFF, 0 );
+        }
+        if ( aExp == 0 ) {
+            ++expDiff;
+        }
+        else {
+            aSig |= 0x20000000;
+        }
+        shift32RightJamming( aSig, - expDiff, &aSig );
+        zExp = bExp;
+    }
+    else {
+        if ( aExp == 0xFF ) {
+            if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+            return a;
+        }
+        if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
+        zSig = 0x40000000 + aSig + bSig;
+        zExp = aExp;
+        goto roundAndPack;
+    }
+    aSig |= 0x20000000;
+    zSig = ( aSig + bSig )<<1;
+    --zExp;
+    if ( (sbits32) zSig < 0 ) {
+        zSig = aSig + bSig;
+        ++zExp;
+    }
+ roundAndPack:
+    return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the single-
+precision floating-point values `a' and `b'.  If `zSign' is 1, the
+difference is negated before being returned.  `zSign' is ignored if the
+result is a NaN.  The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+    int16 aExp, bExp, zExp;
+    bits32 aSig, bSig, zSig;
+    int16 expDiff;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    bSig = extractFloat32Frac( b );
+    bExp = extractFloat32Exp( b );
+    expDiff = aExp - bExp;
+    aSig <<= 7;
+    bSig <<= 7;
+    if ( 0 < expDiff ) goto aExpBigger;
+    if ( expDiff < 0 ) goto bExpBigger;
+    if ( aExp == 0xFF ) {
+        if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+        float_raise( float_flag_invalid );
+        return float32_default_nan;
+    }
+    if ( aExp == 0 ) {
+        aExp = 1;
+        bExp = 1;
+    }
+    if ( bSig < aSig ) goto aBigger;
+    if ( aSig < bSig ) goto bBigger;
+    return packFloat32( float_rounding_mode() == float_round_down, 0, 0 );
+ bExpBigger:
+    if ( bExp == 0xFF ) {
+        if ( bSig ) return propagateFloat32NaN( a, b );
+        return packFloat32( zSign ^ 1, 0xFF, 0 );
+    }
+    if ( aExp == 0 ) {
+        ++expDiff;
+    }
+    else {
+        aSig |= 0x40000000;
+    }
+    shift32RightJamming( aSig, - expDiff, &aSig );
+    bSig |= 0x40000000;
+ bBigger:
+    zSig = bSig - aSig;
+    zExp = bExp;
+    zSign ^= 1;
+    goto normalizeRoundAndPack;
+ aExpBigger:
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return propagateFloat32NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        --expDiff;
+    }
+    else {
+        bSig |= 0x40000000;
+    }
+    shift32RightJamming( bSig, expDiff, &bSig );
+    aSig |= 0x40000000;
+ aBigger:
+    zSig = aSig - bSig;
+    zExp = aExp;
+ normalizeRoundAndPack:
+    --zExp;
+    return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the single-precision floating-point values `a'
+and `b'.  The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_add( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign == bSign ) {
+        return addFloat32Sigs( a, b, aSign );
+    }
+    else {
+        return subFloat32Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the single-precision floating-point values
+`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sub( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign == bSign ) {
+        return subFloat32Sigs( a, b, aSign );
+    }
+    else {
+        return addFloat32Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the single-precision floating-point values
+`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_mul( float32 a, float32 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, zExp;
+    bits32 aSig, bSig;
+    bits64 zSig64;
+    bits32 zSig;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    bSig = extractFloat32Frac( b );
+    bExp = extractFloat32Exp( b );
+    bSign = extractFloat32Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0xFF ) {
+        if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+            return propagateFloat32NaN( a, b );
+        }
+        if ( ( bExp | bSig ) == 0 ) {
+            float_raise( float_flag_invalid );
+            return float32_default_nan;
+        }
+        return packFloat32( zSign, 0xFF, 0 );
+    }
+    if ( bExp == 0xFF ) {
+        if ( bSig ) return propagateFloat32NaN( a, b );
+        if ( ( aExp | aSig ) == 0 ) {
+            float_raise( float_flag_invalid );
+            return float32_default_nan;
+        }
+        return packFloat32( zSign, 0xFF, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
+        normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+    }
+    zExp = aExp + bExp - 0x7F;
+    aSig = ( aSig | 0x00800000 )<<7;
+    bSig = ( bSig | 0x00800000 )<<8;
+    shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
+    zSig = zSig64;
+    if ( 0 <= (sbits32) ( zSig<<1 ) ) {
+        zSig <<= 1;
+        --zExp;
+    }
+    return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the single-precision floating-point value `a'
+by the corresponding value `b'.  The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_div( float32 a, float32 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, zExp;
+    bits32 aSig, bSig, zSig;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    bSig = extractFloat32Frac( b );
+    bExp = extractFloat32Exp( b );
+    bSign = extractFloat32Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return propagateFloat32NaN( a, b );
+        if ( bExp == 0xFF ) {
+            if ( bSig ) return propagateFloat32NaN( a, b );
+            float_raise( float_flag_invalid );
+            return float32_default_nan;
+        }
+        return packFloat32( zSign, 0xFF, 0 );
+    }
+    if ( bExp == 0xFF ) {
+        if ( bSig ) return propagateFloat32NaN( a, b );
+        return packFloat32( zSign, 0, 0 );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+            if ( ( aExp | aSig ) == 0 ) {
+                float_raise( float_flag_invalid );
+                return float32_default_nan;
+            }
+            float_raise( float_flag_divbyzero );
+            return packFloat32( zSign, 0xFF, 0 );
+        }
+        normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+    }
+    zExp = aExp - bExp + 0x7D;
+    aSig = ( aSig | 0x00800000 )<<7;
+    bSig = ( bSig | 0x00800000 )<<8;
+    if ( bSig <= ( aSig + aSig ) ) {
+        aSig >>= 1;
+        ++zExp;
+    }
+    zSig = ( ( (bits64) aSig )<<32 ) / bSig;
+    if ( ( zSig & 0x3F ) == 0 ) {
+        zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 );
+    }
+    return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the single-precision floating-point value `a'
+with respect to the corresponding value `b'.  The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_rem( float32 a, float32 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, expDiff;
+    bits32 aSig, bSig;
+    bits32 q;
+    bits64 aSig64, bSig64, q64;
+    bits32 alternateASig;
+    sbits32 sigMean;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    bSig = extractFloat32Frac( b );
+    bExp = extractFloat32Exp( b );
+    bSign = extractFloat32Sign( b );
+    if ( aExp == 0xFF ) {
+        if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+            return propagateFloat32NaN( a, b );
+        }
+        float_raise( float_flag_invalid );
+        return float32_default_nan;
+    }
+    if ( bExp == 0xFF ) {
+        if ( bSig ) return propagateFloat32NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+            float_raise( float_flag_invalid );
+            return float32_default_nan;
+        }
+        normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return a;
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+    }
+    expDiff = aExp - bExp;
+    aSig |= 0x00800000;
+    bSig |= 0x00800000;
+    if ( expDiff < 32 ) {
+        aSig <<= 8;
+        bSig <<= 8;
+        if ( expDiff < 0 ) {
+            if ( expDiff < -1 ) return a;
+            aSig >>= 1;
+        }
+        q = ( bSig <= aSig );
+        if ( q ) aSig -= bSig;
+        if ( 0 < expDiff ) {
+            q = ( ( (bits64) aSig )<<32 ) / bSig;
+            q >>= 32 - expDiff;
+            bSig >>= 2;
+            aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
+        }
+        else {
+            aSig >>= 2;
+            bSig >>= 2;
+        }
+    }
+    else {
+        if ( bSig <= aSig ) aSig -= bSig;
+        aSig64 = ( (bits64) aSig )<<40;
+        bSig64 = ( (bits64) bSig )<<40;
+        expDiff -= 64;
+        while ( 0 < expDiff ) {
+            q64 = estimateDiv128To64( aSig64, 0, bSig64 );
+            q64 = ( 2 < q64 ) ? q64 - 2 : 0;
+            aSig64 = - ( ( bSig * q64 )<<38 );
+            expDiff -= 62;
+        }
+        expDiff += 64;
+        q64 = estimateDiv128To64( aSig64, 0, bSig64 );
+        q64 = ( 2 < q64 ) ? q64 - 2 : 0;
+        q = q64>>( 64 - expDiff );
+        bSig <<= 6;
+        aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
+    }
+    do {
+        alternateASig = aSig;
+        ++q;
+        aSig -= bSig;
+    } while ( 0 <= (sbits32) aSig );
+    sigMean = aSig + alternateASig;
+    if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
+        aSig = alternateASig;
+    }
+    zSign = ( (sbits32) aSig < 0 );
+    if ( zSign ) aSig = - aSig;
+    return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the single-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sqrt( float32 a )
+{
+    flag aSign;
+    int16 aExp, zExp;
+    bits32 aSig, zSig;
+    bits64 rem, term;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    if ( aExp == 0xFF ) {
+        if ( aSig ) return propagateFloat32NaN( a, 0 );
+        if ( ! aSign ) return a;
+        float_raise( float_flag_invalid );
+        return float32_default_nan;
+    }
+    if ( aSign ) {
+        if ( ( aExp | aSig ) == 0 ) return a;
+        float_raise( float_flag_invalid );
+        return float32_default_nan;
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return 0;
+        normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+    }
+    zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
+    aSig = ( aSig | 0x00800000 )<<8;
+    zSig = estimateSqrt32( aExp, aSig ) + 2;
+    if ( ( zSig & 0x7F ) <= 5 ) {
+        if ( zSig < 2 ) {
+            zSig = 0x7FFFFFFF;
+            goto roundAndPack;
+        }
+        aSig >>= aExp & 1;
+        term = ( (bits64) zSig ) * zSig;
+        rem = ( ( (bits64) aSig )<<32 ) - term;
+        while ( (sbits64) rem < 0 ) {
+            --zSig;
+            rem += ( ( (bits64) zSig )<<1 ) | 1;
+        }
+        zSig |= ( rem != 0 );
+    }
+    shift32RightJamming( zSig, 1, &zSig );
+ roundAndPack:
+    return roundAndPackFloat32( 0, zExp, zSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq( float32 a, float32 b )
+{
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise.  The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+    return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+    return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise.  The invalid exception is
+raised if either operand is a NaN.  Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq_signaling( float32 a, float32 b )
+{
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
+cause an exception.  Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le_quiet( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+    return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+exception.  Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt_quiet( float32 a, float32 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+       ) {
+        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat32Sign( a );
+    bSign = extractFloat32Sign( b );
+    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+    return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32( float64 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
+    if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = 0x42C - aExp;
+    if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
+    return roundAndPackInt32( aSign, aSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32_round_to_zero( float64 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig, savedASig;
+    int32 z;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( 0x41E < aExp ) {
+        if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
+        goto invalid;
+    }
+    else if ( aExp < 0x3FF ) {
+        if ( aExp || aSig ) float_set_inexact();
+        return 0;
+    }
+    aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = 0x433 - aExp;
+    savedASig = aSig;
+    aSig >>= shiftCount;
+    z = aSig;
+    if ( aSign ) z = - z;
+    if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+        float_raise( float_flag_invalid );
+        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+    }
+    if ( ( aSig<<shiftCount ) != savedASig ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 64-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float64_to_int64( float64 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig, aSigExtra;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = 0x433 - aExp;
+    if ( shiftCount <= 0 ) {
+        if ( 0x43E < aExp ) {
+            float_raise( float_flag_invalid );
+            if (    ! aSign
+                 || (    ( aExp == 0x7FF )
+                      && ( aSig != LIT64( 0x0010000000000000 ) ) )
+               ) {
+                return LIT64( 0x7FFFFFFFFFFFFFFF );
+            }
+            return (sbits64) LIT64( 0x8000000000000000 );
+        }
+        aSigExtra = 0;
+        aSig <<= - shiftCount;
+    }
+    else {
+        shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
+    }
+    return roundAndPackInt64( aSign, aSig, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 64-bit two's complement integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float64_to_int64_round_to_zero( float64 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig;
+    int64 z;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = aExp - 0x433;
+    if ( 0 <= shiftCount ) {
+        if ( 0x43E <= aExp ) {
+            if ( a != LIT64( 0xC3E0000000000000 ) ) {
+                float_raise( float_flag_invalid );
+                if (    ! aSign
+                     || (    ( aExp == 0x7FF )
+                          && ( aSig != LIT64( 0x0010000000000000 ) ) )
+                   ) {
+                    return LIT64( 0x7FFFFFFFFFFFFFFF );
+                }
+            }
+            return (sbits64) LIT64( 0x8000000000000000 );
+        }
+        z = aSig<<shiftCount;
+    }
+    else {
+        if ( aExp < 0x3FE ) {
+            if ( aExp | aSig ) float_set_inexact();
+            return 0;
+        }
+        z = aSig>>( - shiftCount );
+        if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+            float_set_inexact();
+        }
+    }
+    if ( aSign ) z = - z;
+    return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the single-precision floating-point format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float64_to_float32( float64 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits64 aSig;
+    bits32 zSig;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) );
+        return packFloat32( aSign, 0xFF, 0 );
+    }
+    shift64RightJamming( aSig, 22, &aSig );
+    zSig = aSig;
+    if ( aExp || zSig ) {
+        zSig |= 0x40000000;
+        aExp -= 0x381;
+    }
+    return roundAndPackFloat32( aSign, aExp, zSig );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the extended double-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float64_to_floatx80( float64 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits64 aSig;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) );
+        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+    }
+    return
+        packFloatx80(
+            aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the quadruple-precision floating-point format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float64_to_float128( float64 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits64 aSig, zSig0, zSig1;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) );
+        return packFloat128( aSign, 0x7FFF, 0, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+        --aExp;
+    }
+    shift128Right( aSig, 0, 4, &zSig0, &zSig1 );
+    return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Rounds the double-precision floating-point value `a' to an integer, and
+returns the result as a double-precision floating-point value.  The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits64 lastBitMask, roundBitsMask;
+    int8 roundingMode;
+    float64 z;
+
+    aExp = extractFloat64Exp( a );
+    if ( 0x433 <= aExp ) {
+        if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
+            return propagateFloat64NaN( a, a );
+        }
+        return a;
+    }
+    if ( aExp < 0x3FF ) {
+        if ( (bits64) ( a<<1 ) == 0 ) return a;
+        float_set_inexact();
+        aSign = extractFloat64Sign( a );
+        switch ( float_rounding_mode() ) {
+         case float_round_nearest_even:
+            if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
+                return packFloat64( aSign, 0x3FF, 0 );
+            }
+            break;
+         case float_round_down:
+            return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
+         case float_round_up:
+            return
+            aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
+        }
+        return packFloat64( aSign, 0, 0 );
+    }
+    lastBitMask = 1;
+    lastBitMask <<= 0x433 - aExp;
+    roundBitsMask = lastBitMask - 1;
+    z = a;
+    roundingMode = float_rounding_mode();
+    if ( roundingMode == float_round_nearest_even ) {
+        z += lastBitMask>>1;
+        if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
+    }
+    else if ( roundingMode != float_round_to_zero ) {
+        if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+            z += roundBitsMask;
+        }
+    }
+    z &= ~ roundBitsMask;
+    if ( z != a ) float_set_inexact();
+    return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the double-precision
+floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
+before being returned.  `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+    int16 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig;
+    int16 expDiff;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    bSig = extractFloat64Frac( b );
+    bExp = extractFloat64Exp( b );
+    expDiff = aExp - bExp;
+    aSig <<= 9;
+    bSig <<= 9;
+    if ( 0 < expDiff ) {
+        if ( aExp == 0x7FF ) {
+            if ( aSig ) return propagateFloat64NaN( a, b );
+            return a;
+        }
+        if ( bExp == 0 ) {
+            --expDiff;
+        }
+        else {
+            bSig |= LIT64( 0x2000000000000000 );
+        }
+        shift64RightJamming( bSig, expDiff, &bSig );
+        zExp = aExp;
+    }
+    else if ( expDiff < 0 ) {
+        if ( bExp == 0x7FF ) {
+            if ( bSig ) return propagateFloat64NaN( a, b );
+            return packFloat64( zSign, 0x7FF, 0 );
+        }
+        if ( aExp == 0 ) {
+            ++expDiff;
+        }
+        else {
+            aSig |= LIT64( 0x2000000000000000 );
+        }
+        shift64RightJamming( aSig, - expDiff, &aSig );
+        zExp = bExp;
+    }
+    else {
+        if ( aExp == 0x7FF ) {
+            if ( aSig | bSig ) return propagateFloat64NaN( a, b );
+            return a;
+        }
+        if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
+        zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
+        zExp = aExp;
+        goto roundAndPack;
+    }
+    aSig |= LIT64( 0x2000000000000000 );
+    zSig = ( aSig + bSig )<<1;
+    --zExp;
+    if ( (sbits64) zSig < 0 ) {
+        zSig = aSig + bSig;
+        ++zExp;
+    }
+ roundAndPack:
+    return roundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the double-
+precision floating-point values `a' and `b'.  If `zSign' is 1, the
+difference is negated before being returned.  `zSign' is ignored if the
+result is a NaN.  The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+    int16 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig;
+    int16 expDiff;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    bSig = extractFloat64Frac( b );
+    bExp = extractFloat64Exp( b );
+    expDiff = aExp - bExp;
+    aSig <<= 10;
+    bSig <<= 10;
+    if ( 0 < expDiff ) goto aExpBigger;
+    if ( expDiff < 0 ) goto bExpBigger;
+    if ( aExp == 0x7FF ) {
+        if ( aSig | bSig ) return propagateFloat64NaN( a, b );
+        float_raise( float_flag_invalid );
+        return float64_default_nan;
+    }
+    if ( aExp == 0 ) {
+        aExp = 1;
+        bExp = 1;
+    }
+    if ( bSig < aSig ) goto aBigger;
+    if ( aSig < bSig ) goto bBigger;
+    return packFloat64( float_rounding_mode() == float_round_down, 0, 0 );
+ bExpBigger:
+    if ( bExp == 0x7FF ) {
+        if ( bSig ) return propagateFloat64NaN( a, b );
+        return packFloat64( zSign ^ 1, 0x7FF, 0 );
+    }
+    if ( aExp == 0 ) {
+        ++expDiff;
+    }
+    else {
+        aSig |= LIT64( 0x4000000000000000 );
+    }
+    shift64RightJamming( aSig, - expDiff, &aSig );
+    bSig |= LIT64( 0x4000000000000000 );
+ bBigger:
+    zSig = bSig - aSig;
+    zExp = bExp;
+    zSign ^= 1;
+    goto normalizeRoundAndPack;
+ aExpBigger:
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return propagateFloat64NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        --expDiff;
+    }
+    else {
+        bSig |= LIT64( 0x4000000000000000 );
+    }
+    shift64RightJamming( bSig, expDiff, &bSig );
+    aSig |= LIT64( 0x4000000000000000 );
+ aBigger:
+    zSig = aSig - bSig;
+    zExp = aExp;
+ normalizeRoundAndPack:
+    --zExp;
+    return normalizeRoundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the double-precision floating-point values `a'
+and `b'.  The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_add( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign == bSign ) {
+        return addFloat64Sigs( a, b, aSign );
+    }
+    else {
+        return subFloat64Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the double-precision floating-point values
+`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sub( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign == bSign ) {
+        return subFloat64Sigs( a, b, aSign );
+    }
+    else {
+        return addFloat64Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the double-precision floating-point values
+`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_mul( float64 a, float64 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig0, zSig1;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    bSig = extractFloat64Frac( b );
+    bExp = extractFloat64Exp( b );
+    bSign = extractFloat64Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FF ) {
+        if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
+            return propagateFloat64NaN( a, b );
+        }
+        if ( ( bExp | bSig ) == 0 ) {
+            float_raise( float_flag_invalid );
+            return float64_default_nan;
+        }
+        return packFloat64( zSign, 0x7FF, 0 );
+    }
+    if ( bExp == 0x7FF ) {
+        if ( bSig ) return propagateFloat64NaN( a, b );
+        if ( ( aExp | aSig ) == 0 ) {
+            float_raise( float_flag_invalid );
+            return float64_default_nan;
+        }
+        return packFloat64( zSign, 0x7FF, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
+        normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+    }
+    zExp = aExp + bExp - 0x3FF;
+    aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
+    bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+    mul64To128( aSig, bSig, &zSig0, &zSig1 );
+    zSig0 |= ( zSig1 != 0 );
+    if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
+        zSig0 <<= 1;
+        --zExp;
+    }
+    return roundAndPackFloat64( zSign, zExp, zSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the double-precision floating-point value `a'
+by the corresponding value `b'.  The operation is performed according to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_div( float64 a, float64 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig;
+    bits64 rem0, rem1;
+    bits64 term0, term1;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    bSig = extractFloat64Frac( b );
+    bExp = extractFloat64Exp( b );
+    bSign = extractFloat64Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return propagateFloat64NaN( a, b );
+        if ( bExp == 0x7FF ) {
+            if ( bSig ) return propagateFloat64NaN( a, b );
+            float_raise( float_flag_invalid );
+            return float64_default_nan;
+        }
+        return packFloat64( zSign, 0x7FF, 0 );
+    }
+    if ( bExp == 0x7FF ) {
+        if ( bSig ) return propagateFloat64NaN( a, b );
+        return packFloat64( zSign, 0, 0 );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+            if ( ( aExp | aSig ) == 0 ) {
+                float_raise( float_flag_invalid );
+                return float64_default_nan;
+            }
+            float_raise( float_flag_divbyzero );
+            return packFloat64( zSign, 0x7FF, 0 );
+        }
+        normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+    }
+    zExp = aExp - bExp + 0x3FD;
+    aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
+    bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+    if ( bSig <= ( aSig + aSig ) ) {
+        aSig >>= 1;
+        ++zExp;
+    }
+    zSig = estimateDiv128To64( aSig, 0, bSig );
+    if ( ( zSig & 0x1FF ) <= 2 ) {
+        mul64To128( bSig, zSig, &term0, &term1 );
+        sub128( aSig, 0, term0, term1, &rem0, &rem1 );
+        while ( (sbits64) rem0 < 0 ) {
+            --zSig;
+            add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
+        }
+        zSig |= ( rem1 != 0 );
+    }
+    return roundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the double-precision floating-point value `a'
+with respect to the corresponding value `b'.  The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_rem( float64 a, float64 b )
+{
+    flag aSign, bSign, zSign;
+    int16 aExp, bExp, expDiff;
+    bits64 aSig, bSig;
+    bits64 q, alternateASig;
+    sbits64 sigMean;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    bSig = extractFloat64Frac( b );
+    bExp = extractFloat64Exp( b );
+    bSign = extractFloat64Sign( b );
+    if ( aExp == 0x7FF ) {
+        if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
+            return propagateFloat64NaN( a, b );
+        }
+        float_raise( float_flag_invalid );
+        return float64_default_nan;
+    }
+    if ( bExp == 0x7FF ) {
+        if ( bSig ) return propagateFloat64NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+            float_raise( float_flag_invalid );
+            return float64_default_nan;
+        }
+        normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return a;
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+    }
+    expDiff = aExp - bExp;
+    aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
+    bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+    if ( expDiff < 0 ) {
+        if ( expDiff < -1 ) return a;
+        aSig >>= 1;
+    }
+    q = ( bSig <= aSig );
+    if ( q ) aSig -= bSig;
+    expDiff -= 64;
+    while ( 0 < expDiff ) {
+        q = estimateDiv128To64( aSig, 0, bSig );
+        q = ( 2 < q ) ? q - 2 : 0;
+        aSig = - ( ( bSig>>2 ) * q );
+        expDiff -= 62;
+    }
+    expDiff += 64;
+    if ( 0 < expDiff ) {
+        q = estimateDiv128To64( aSig, 0, bSig );
+        q = ( 2 < q ) ? q - 2 : 0;
+        q >>= 64 - expDiff;
+        bSig >>= 2;
+        aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
+    }
+    else {
+        aSig >>= 2;
+        bSig >>= 2;
+    }
+    do {
+        alternateASig = aSig;
+        ++q;
+        aSig -= bSig;
+    } while ( 0 <= (sbits64) aSig );
+    sigMean = aSig + alternateASig;
+    if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
+        aSig = alternateASig;
+    }
+    zSign = ( (sbits64) aSig < 0 );
+    if ( zSign ) aSig = - aSig;
+    return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the double-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sqrt( float64 a )
+{
+    flag aSign;
+    int16 aExp, zExp;
+    bits64 aSig, zSig, doubleZSig;
+    bits64 rem0, rem1, term0, term1;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+    if ( aExp == 0x7FF ) {
+        if ( aSig ) return propagateFloat64NaN( a, a );
+        if ( ! aSign ) return a;
+        float_raise( float_flag_invalid );
+        return float64_default_nan;
+    }
+    if ( aSign ) {
+        if ( ( aExp | aSig ) == 0 ) return a;
+        float_raise( float_flag_invalid );
+        return float64_default_nan;
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return 0;
+        normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+    }
+    zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
+    aSig |= LIT64( 0x0010000000000000 );
+    zSig = estimateSqrt32( aExp, aSig>>21 );
+    aSig <<= 9 - ( aExp & 1 );
+    zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 );
+    if ( ( zSig & 0x1FF ) <= 5 ) {
+        doubleZSig = zSig<<1;
+        mul64To128( zSig, zSig, &term0, &term1 );
+        sub128( aSig, 0, term0, term1, &rem0, &rem1 );
+        while ( (sbits64) rem0 < 0 ) {
+            --zSig;
+            doubleZSig -= 2;
+            add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
+        }
+        zSig |= ( ( rem0 | rem1 ) != 0 );
+    }
+    return roundAndPackFloat64( 0, zExp, zSig );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to the
+corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq( float64 a, float64 b )
+{
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    return ( a == b ) ||
+       ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise.  The comparison is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign != bSign )
+       return aSign ||
+           ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) ==
+             0 );
+    return ( a == b ) ||
+       ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign != bSign )
+       return aSign &&
+           ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) !=
+             0 );
+    return ( a != b ) &&
+       ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to the
+corresponding value `b', and 0 otherwise.  The invalid exception is raised
+if either operand is a NaN.  Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq_signaling( float64 a, float64 b )
+{
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
+cause an exception.  Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le_quiet( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
+    return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+exception.  Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt_quiet( float64 a, float64 b )
+{
+    flag aSign, bSign;
+
+    if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+         || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+       ) {
+        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
+    return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 32-bit two's complement integer format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic---which means in particular that the conversion
+is rounded according to the current rounding mode.  If `a' is a NaN, the
+largest positive integer is returned.  Otherwise, if the conversion
+overflows, the largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 floatx80_to_int32( floatx80 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+    shiftCount = 0x4037 - aExp;
+    if ( shiftCount <= 0 ) shiftCount = 1;
+    shift64RightJamming( aSig, shiftCount, &aSig );
+    return roundAndPackInt32( aSign, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 32-bit two's complement integer format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic, except that the conversion is always rounded
+toward zero.  If `a' is a NaN, the largest positive integer is returned.
+Otherwise, if the conversion overflows, the largest integer with the same
+sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 floatx80_to_int32_round_to_zero( floatx80 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig, savedASig;
+    int32 z;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( 0x401E < aExp ) {
+        if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+        goto invalid;
+    }
+    else if ( aExp < 0x3FFF ) {
+        if ( aExp || aSig ) float_set_inexact();
+        return 0;
+    }
+    shiftCount = 0x403E - aExp;
+    savedASig = aSig;
+    aSig >>= shiftCount;
+    z = aSig;
+    if ( aSign ) z = - z;
+    if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+        float_raise( float_flag_invalid );
+        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+    }
+    if ( ( aSig<<shiftCount ) != savedASig ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 64-bit two's complement integer format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic---which means in particular that the conversion
+is rounded according to the current rounding mode.  If `a' is a NaN,
+the largest positive integer is returned.  Otherwise, if the conversion
+overflows, the largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 floatx80_to_int64( floatx80 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig, aSigExtra;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    shiftCount = 0x403E - aExp;
+    if ( shiftCount <= 0 ) {
+        if ( shiftCount ) {
+            float_raise( float_flag_invalid );
+            if (    ! aSign
+                 || (    ( aExp == 0x7FFF )
+                      && ( aSig != LIT64( 0x8000000000000000 ) ) )
+               ) {
+                return LIT64( 0x7FFFFFFFFFFFFFFF );
+            }
+            return (sbits64) LIT64( 0x8000000000000000 );
+        }
+        aSigExtra = 0;
+    }
+    else {
+        shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
+    }
+    return roundAndPackInt64( aSign, aSig, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 64-bit two's complement integer format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic, except that the conversion is always rounded
+toward zero.  If `a' is a NaN, the largest positive integer is returned.
+Otherwise, if the conversion overflows, the largest integer with the same
+sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 floatx80_to_int64_round_to_zero( floatx80 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig;
+    int64 z;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    shiftCount = aExp - 0x403E;
+    if ( 0 <= shiftCount ) {
+        aSig &= LIT64( 0x7FFFFFFFFFFFFFFF );
+        if ( ( a.high != 0xC03E ) || aSig ) {
+            float_raise( float_flag_invalid );
+            if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) {
+                return LIT64( 0x7FFFFFFFFFFFFFFF );
+            }
+        }
+        return (sbits64) LIT64( 0x8000000000000000 );
+    }
+    else if ( aExp < 0x3FFF ) {
+        if ( aExp | aSig ) float_set_inexact();
+        return 0;
+    }
+    z = aSig>>( - shiftCount );
+    if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+        float_set_inexact();
+    }
+    if ( aSign ) z = - z;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the single-precision floating-point format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 floatx80_to_float32( floatx80 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 aSig;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( aSig<<1 ) ) {
+            return commonNaNToFloat32( floatx80ToCommonNaN( a ) );
+        }
+        return packFloat32( aSign, 0xFF, 0 );
+    }
+    shift64RightJamming( aSig, 33, &aSig );
+    if ( aExp || aSig ) aExp -= 0x3F81;
+    return roundAndPackFloat32( aSign, aExp, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the double-precision floating-point format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 floatx80_to_float64( floatx80 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 aSig, zSig;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( aSig<<1 ) ) {
+            return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
+        }
+        return packFloat64( aSign, 0x7FF, 0 );
+    }
+    shift64RightJamming( aSig, 1, &zSig );
+    if ( aExp || aSig ) aExp -= 0x3C01;
+    return roundAndPackFloat64( aSign, aExp, zSig );
+
+}
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the quadruple-precision floating-point format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 floatx80_to_float128( floatx80 a )
+{
+    flag aSign;
+    int16 aExp;
+    bits64 aSig, zSig0, zSig1;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
+        return commonNaNToFloat128( floatx80ToCommonNaN( a ) );
+    }
+    shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
+    return packFloat128( aSign, aExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Rounds the extended double-precision floating-point value `a' to an integer,
+and returns the result as an extended quadruple-precision floating-point
+value.  The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 lastBitMask, roundBitsMask;
+    int8 roundingMode;
+    floatx80 z;
+
+    aExp = extractFloatx80Exp( a );
+    if ( 0x403E <= aExp ) {
+        if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
+            return propagateFloatx80NaN( a, a );
+        }
+        return a;
+    }
+    if ( aExp < 0x3FFF ) {
+        if (    ( aExp == 0 )
+             && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+            return a;
+        }
+        float_set_inexact();
+        aSign = extractFloatx80Sign( a );
+        switch ( float_rounding_mode() ) {
+         case float_round_nearest_even:
+            if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
+               ) {
+                return
+                    packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+            }
+            break;
+         case float_round_down:
+            return
+                  aSign ?
+                      packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
+                : packFloatx80( 0, 0, 0 );
+         case float_round_up:
+            return
+                  aSign ? packFloatx80( 1, 0, 0 )
+                : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
+        }
+        return packFloatx80( aSign, 0, 0 );
+    }
+    lastBitMask = 1;
+    lastBitMask <<= 0x403E - aExp;
+    roundBitsMask = lastBitMask - 1;
+    z = a;
+    roundingMode = float_rounding_mode();
+    if ( roundingMode == float_round_nearest_even ) {
+        z.low += lastBitMask>>1;
+        if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+    }
+    else if ( roundingMode != float_round_to_zero ) {
+        if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+            z.low += roundBitsMask;
+        }
+    }
+    z.low &= ~ roundBitsMask;
+    if ( z.low == 0 ) {
+        ++z.high;
+        z.low = LIT64( 0x8000000000000000 );
+    }
+    if ( z.low != a.low ) float_set_inexact();
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the extended double-
+precision floating-point values `a' and `b'.  If `zSign' is 1, the sum is
+negated before being returned.  `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+    int32 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig0, zSig1;
+    int32 expDiff;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    expDiff = aExp - bExp;
+    if ( 0 < expDiff ) {
+        if ( aExp == 0x7FFF ) {
+            if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+            return a;
+        }
+        if ( bExp == 0 ) --expDiff;
+        shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+        zExp = aExp;
+    }
+    else if ( expDiff < 0 ) {
+        if ( bExp == 0x7FFF ) {
+            if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        }
+        if ( aExp == 0 ) ++expDiff;
+        shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+        zExp = bExp;
+    }
+    else {
+        if ( aExp == 0x7FFF ) {
+            if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+                return propagateFloatx80NaN( a, b );
+            }
+            return a;
+        }
+        zSig1 = 0;
+        zSig0 = aSig + bSig;
+        if ( aExp == 0 ) {
+            normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
+            goto roundAndPack;
+        }
+        zExp = aExp;
+        goto shiftRight1;
+    }
+    zSig0 = aSig + bSig;
+    if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
+ shiftRight1:
+    shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
+    zSig0 |= LIT64( 0x8000000000000000 );
+    ++zExp;
+ roundAndPack:
+    return
+        roundAndPackFloatx80(
+            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the extended
+double-precision floating-point values `a' and `b'.  If `zSign' is 1, the
+difference is negated before being returned.  `zSign' is ignored if the
+result is a NaN.  The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+    int32 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig0, zSig1;
+    int32 expDiff;
+    floatx80 z;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    expDiff = aExp - bExp;
+    if ( 0 < expDiff ) goto aExpBigger;
+    if ( expDiff < 0 ) goto bExpBigger;
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+            return propagateFloatx80NaN( a, b );
+        }
+        float_raise( float_flag_invalid );
+        z.low = floatx80_default_nan_low;
+        z.high = floatx80_default_nan_high;
+        return z;
+    }
+    if ( aExp == 0 ) {
+        aExp = 1;
+        bExp = 1;
+    }
+    zSig1 = 0;
+    if ( bSig < aSig ) goto aBigger;
+    if ( aSig < bSig ) goto bBigger;
+    return packFloatx80( float_rounding_mode() == float_round_down, 0, 0 );
+ bExpBigger:
+    if ( bExp == 0x7FFF ) {
+        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( aExp == 0 ) ++expDiff;
+    shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+ bBigger:
+    sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
+    zExp = bExp;
+    zSign ^= 1;
+    goto normalizeRoundAndPack;
+ aExpBigger:
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) --expDiff;
+    shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+ aBigger:
+    sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
+    zExp = aExp;
+ normalizeRoundAndPack:
+    return
+        normalizeRoundAndPackFloatx80(
+            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the extended double-precision floating-point
+values `a' and `b'.  The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_add( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign == bSign ) {
+        return addFloatx80Sigs( a, b, aSign );
+    }
+    else {
+        return subFloatx80Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the extended double-precision floating-
+point values `a' and `b'.  The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_sub( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign == bSign ) {
+        return subFloatx80Sigs( a, b, aSign );
+    }
+    else {
+        return addFloatx80Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the extended double-precision floating-
+point values `a' and `b'.  The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_mul( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig0, zSig1;
+    floatx80 z;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    bSign = extractFloatx80Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FFF ) {
+        if (    (bits64) ( aSig<<1 )
+             || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+            return propagateFloatx80NaN( a, b );
+        }
+        if ( ( bExp | bSig ) == 0 ) goto invalid;
+        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+            float_raise( float_flag_invalid );
+            z.low = floatx80_default_nan_low;
+            z.high = floatx80_default_nan_high;
+            return z;
+        }
+        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+        normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
+        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+    }
+    zExp = aExp + bExp - 0x3FFE;
+    mul64To128( aSig, bSig, &zSig0, &zSig1 );
+    if ( 0 < (sbits64) zSig0 ) {
+        shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
+        --zExp;
+    }
+    return
+        roundAndPackFloatx80(
+            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the extended double-precision floating-point
+value `a' by the corresponding value `b'.  The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_div( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, zExp;
+    bits64 aSig, bSig, zSig0, zSig1;
+    bits64 rem0, rem1, rem2, term0, term1, term2;
+    floatx80 z;
+
+    aSig = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    bSign = extractFloatx80Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        if ( bExp == 0x7FFF ) {
+            if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+            goto invalid;
+        }
+        return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        return packFloatx80( zSign, 0, 0 );
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+            if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+                float_raise( float_flag_invalid );
+                z.low = floatx80_default_nan_low;
+                z.high = floatx80_default_nan_high;
+                return z;
+            }
+            float_raise( float_flag_divbyzero );
+            return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+        }
+        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+        normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+    }
+    zExp = aExp - bExp + 0x3FFE;
+    rem1 = 0;
+    if ( bSig <= aSig ) {
+        shift128Right( aSig, 0, 1, &aSig, &rem1 );
+        ++zExp;
+    }
+    zSig0 = estimateDiv128To64( aSig, rem1, bSig );
+    mul64To128( bSig, zSig0, &term0, &term1 );
+    sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
+    while ( (sbits64) rem0 < 0 ) {
+        --zSig0;
+        add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
+    }
+    zSig1 = estimateDiv128To64( rem1, 0, bSig );
+    if ( (bits64) ( zSig1<<1 ) <= 8 ) {
+        mul64To128( bSig, zSig1, &term1, &term2 );
+        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+        while ( (sbits64) rem1 < 0 ) {
+            --zSig1;
+            add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
+        }
+        zSig1 |= ( ( rem1 | rem2 ) != 0 );
+    }
+    return
+        roundAndPackFloatx80(
+            floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the extended double-precision floating-point value
+`a' with respect to the corresponding value `b'.  The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_rem( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, expDiff;
+    bits64 aSig0, aSig1, bSig;
+    bits64 q, term0, term1, alternateASig0, alternateASig1;
+    floatx80 z;
+
+    aSig0 = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    bSig = extractFloatx80Frac( b );
+    bExp = extractFloatx80Exp( b );
+    bSign = extractFloatx80Sign( b );
+    if ( aExp == 0x7FFF ) {
+        if (    (bits64) ( aSig0<<1 )
+             || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+            return propagateFloatx80NaN( a, b );
+        }
+        goto invalid;
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        if ( bSig == 0 ) {
+ invalid:
+            float_raise( float_flag_invalid );
+            z.low = floatx80_default_nan_low;
+            z.high = floatx80_default_nan_high;
+            return z;
+        }
+        normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+    }
+    if ( aExp == 0 ) {
+        if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
+        normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+    }
+    bSig |= LIT64( 0x8000000000000000 );
+    zSign = aSign;
+    expDiff = aExp - bExp;
+    aSig1 = 0;
+    if ( expDiff < 0 ) {
+        if ( expDiff < -1 ) return a;
+        shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
+        expDiff = 0;
+    }
+    q = ( bSig <= aSig0 );
+    if ( q ) aSig0 -= bSig;
+    expDiff -= 64;
+    while ( 0 < expDiff ) {
+        q = estimateDiv128To64( aSig0, aSig1, bSig );
+        q = ( 2 < q ) ? q - 2 : 0;
+        mul64To128( bSig, q, &term0, &term1 );
+        sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+        shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
+        expDiff -= 62;
+    }
+    expDiff += 64;
+    if ( 0 < expDiff ) {
+        q = estimateDiv128To64( aSig0, aSig1, bSig );
+        q = ( 2 < q ) ? q - 2 : 0;
+        q >>= 64 - expDiff;
+        mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
+        sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+        shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
+        while ( le128( term0, term1, aSig0, aSig1 ) ) {
+            ++q;
+            sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+        }
+    }
+    else {
+        term1 = 0;
+        term0 = bSig;
+    }
+    sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
+    if (    lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
+         || (    eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
+              && ( q & 1 ) )
+       ) {
+        aSig0 = alternateASig0;
+        aSig1 = alternateASig1;
+        zSign = ! zSign;
+    }
+    return
+        normalizeRoundAndPackFloatx80(
+            80, zSign, bExp + expDiff, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the extended double-precision floating-point
+value `a'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_sqrt( floatx80 a )
+{
+    flag aSign;
+    int32 aExp, zExp;
+    bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0;
+    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    floatx80 z;
+
+    aSig0 = extractFloatx80Frac( a );
+    aExp = extractFloatx80Exp( a );
+    aSign = extractFloatx80Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a );
+        if ( ! aSign ) return a;
+        goto invalid;
+    }
+    if ( aSign ) {
+        if ( ( aExp | aSig0 ) == 0 ) return a;
+ invalid:
+        float_raise( float_flag_invalid );
+        z.low = floatx80_default_nan_low;
+        z.high = floatx80_default_nan_high;
+        return z;
+    }
+    if ( aExp == 0 ) {
+        if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
+        normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+    }
+    zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
+    zSig0 = estimateSqrt32( aExp, aSig0>>32 );
+    shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
+    zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
+    doubleZSig0 = zSig0<<1;
+    mul64To128( zSig0, zSig0, &term0, &term1 );
+    sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+    while ( (sbits64) rem0 < 0 ) {
+        --zSig0;
+        doubleZSig0 -= 2;
+        add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
+    }
+    zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
+    if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
+        if ( zSig1 == 0 ) zSig1 = 1;
+        mul64To128( doubleZSig0, zSig1, &term1, &term2 );
+        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+        mul64To128( zSig1, zSig1, &term2, &term3 );
+        sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+        while ( (sbits64) rem1 < 0 ) {
+            --zSig1;
+            shortShift128Left( 0, zSig1, 1, &term2, &term3 );
+            term3 |= 1;
+            term2 |= doubleZSig0;
+            add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+        }
+        zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+    }
+    shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
+    zSig0 |= doubleZSig0;
+    return
+        roundAndPackFloatx80(
+            floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+equal to the corresponding value `b', and 0 otherwise.  The comparison is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_eq( floatx80 a, floatx80 b )
+{
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        if (    floatx80_is_signaling_nan( a )
+             || floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    return
+           ( a.low == b.low )
+        && (    ( a.high == b.high )
+             || (    ( a.low == 0 )
+                  && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+           );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+less than or equal to the corresponding value `b', and 0 otherwise.  The
+comparison is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_le( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 == 0 );
+    }
+    return
+          aSign ? le128( b.high, b.low, a.high, a.low )
+        : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+less than the corresponding value `b', and 0 otherwise.  The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_lt( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 != 0 );
+    }
+    return
+          aSign ? lt128( b.high, b.low, a.high, a.low )
+        : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is equal
+to the corresponding value `b', and 0 otherwise.  The invalid exception is
+raised if either operand is a NaN.  Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_eq_signaling( floatx80 a, floatx80 b )
+{
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    return
+           ( a.low == b.low )
+        && (    ( a.high == b.high )
+             || (    ( a.low == 0 )
+                  && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+           );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is less
+than or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs
+do not cause an exception.  Otherwise, the comparison is performed according
+to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_le_quiet( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        if (    floatx80_is_signaling_nan( a )
+             || floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            || (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 == 0 );
+    }
+    return
+          aSign ? le128( b.high, b.low, a.high, a.low )
+        : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is less
+than the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause
+an exception.  Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_lt_quiet( floatx80 a, floatx80 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+         || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+              && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+       ) {
+        if (    floatx80_is_signaling_nan( a )
+             || floatx80_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloatx80Sign( a );
+    bSign = extractFloatx80Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            && (    ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 != 0 );
+    }
+    return
+          aSign ? lt128( b.high, b.low, a.high, a.low )
+        : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 32-bit two's complement integer format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float128_to_int32( float128 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig0, aSig1;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0;
+    if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+    aSig0 |= ( aSig1 != 0 );
+    shiftCount = 0x4028 - aExp;
+    if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 );
+    return roundAndPackInt32( aSign, aSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 32-bit two's complement integer format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.  If
+`a' is a NaN, the largest positive integer is returned.  Otherwise, if the
+conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float128_to_int32_round_to_zero( float128 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig0, aSig1, savedASig;
+    int32 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    aSig0 |= ( aSig1 != 0 );
+    if ( 0x401E < aExp ) {
+        if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0;
+        goto invalid;
+    }
+    else if ( aExp < 0x3FFF ) {
+        if ( aExp || aSig0 ) float_set_inexact();
+        return 0;
+    }
+    aSig0 |= LIT64( 0x0001000000000000 );
+    shiftCount = 0x402F - aExp;
+    savedASig = aSig0;
+    aSig0 >>= shiftCount;
+    z = aSig0;
+    if ( aSign ) z = - z;
+    if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+        float_raise( float_flag_invalid );
+        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+    }
+    if ( ( aSig0<<shiftCount ) != savedASig ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 64-bit two's complement integer format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode.  If `a' is a NaN, the largest
+positive integer is returned.  Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float128_to_int64( float128 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig0, aSig1;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+    shiftCount = 0x402F - aExp;
+    if ( shiftCount <= 0 ) {
+        if ( 0x403E < aExp ) {
+            float_raise( float_flag_invalid );
+            if (    ! aSign
+                 || (    ( aExp == 0x7FFF )
+                      && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) )
+                    )
+               ) {
+                return LIT64( 0x7FFFFFFFFFFFFFFF );
+            }
+            return (sbits64) LIT64( 0x8000000000000000 );
+        }
+        shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
+    }
+    else {
+        shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 );
+    }
+    return roundAndPackInt64( aSign, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 64-bit two's complement integer format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float128_to_int64_round_to_zero( float128 a )
+{
+    flag aSign;
+    int32 aExp, shiftCount;
+    bits64 aSig0, aSig1;
+    int64 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+    shiftCount = aExp - 0x402F;
+    if ( 0 < shiftCount ) {
+        if ( 0x403E <= aExp ) {
+            aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
+            if (    ( a.high == LIT64( 0xC03E000000000000 ) )
+                 && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
+                if ( aSig1 ) float_set_inexact();
+            }
+            else {
+                float_raise( float_flag_invalid );
+                if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) {
+                    return LIT64( 0x7FFFFFFFFFFFFFFF );
+                }
+            }
+            return (sbits64) LIT64( 0x8000000000000000 );
+        }
+        z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
+        if ( (bits64) ( aSig1<<shiftCount ) ) {
+            float_set_inexact();
+        }
+    }
+    else {
+        if ( aExp < 0x3FFF ) {
+            if ( aExp | aSig0 | aSig1 ) {
+                float_set_inexact();
+            }
+            return 0;
+        }
+        z = aSig0>>( - shiftCount );
+        if (    aSig1
+             || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
+            float_set_inexact();
+        }
+    }
+    if ( aSign ) z = - z;
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the single-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float128_to_float32( float128 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 aSig0, aSig1;
+    bits32 zSig;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) {
+            return commonNaNToFloat32( float128ToCommonNaN( a ) );
+        }
+        return packFloat32( aSign, 0xFF, 0 );
+    }
+    aSig0 |= ( aSig1 != 0 );
+    shift64RightJamming( aSig0, 18, &aSig0 );
+    zSig = aSig0;
+    if ( aExp || zSig ) {
+        zSig |= 0x40000000;
+        aExp -= 0x3F81;
+    }
+    return roundAndPackFloat32( aSign, aExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the double-precision floating-point format.  The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float128_to_float64( float128 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 aSig0, aSig1;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) {
+            return commonNaNToFloat64( float128ToCommonNaN( a ) );
+        }
+        return packFloat64( aSign, 0x7FF, 0 );
+    }
+    shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
+    aSig0 |= ( aSig1 != 0 );
+    if ( aExp || aSig0 ) {
+        aSig0 |= LIT64( 0x4000000000000000 );
+        aExp -= 0x3C01;
+    }
+    return roundAndPackFloat64( aSign, aExp, aSig0 );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the extended double-precision floating-point format.  The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float128_to_floatx80( float128 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 aSig0, aSig1;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) {
+            return commonNaNToFloatx80( float128ToCommonNaN( a ) );
+        }
+        return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+    }
+    if ( aExp == 0 ) {
+        if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
+        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+    }
+    else {
+        aSig0 |= LIT64( 0x0001000000000000 );
+    }
+    shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
+    return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Rounds the quadruple-precision floating-point value `a' to an integer, and
+returns the result as a quadruple-precision floating-point value.  The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 a )
+{
+    flag aSign;
+    int32 aExp;
+    bits64 lastBitMask, roundBitsMask;
+    int8 roundingMode;
+    float128 z;
+
+    aExp = extractFloat128Exp( a );
+    if ( 0x402F <= aExp ) {
+        if ( 0x406F <= aExp ) {
+            if (    ( aExp == 0x7FFF )
+                 && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )
+               ) {
+                return propagateFloat128NaN( a, a );
+            }
+            return a;
+        }
+        lastBitMask = 1;
+        lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
+        roundBitsMask = lastBitMask - 1;
+        z = a;
+        roundingMode = float_rounding_mode();
+        if ( roundingMode == float_round_nearest_even ) {
+            if ( lastBitMask ) {
+                add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
+                if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+            }
+            else {
+                if ( (sbits64) z.low < 0 ) {
+                    ++z.high;
+                    if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1;
+                }
+            }
+        }
+        else if ( roundingMode != float_round_to_zero ) {
+            if (   extractFloat128Sign( z )
+                 ^ ( roundingMode == float_round_up ) ) {
+                add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
+            }
+        }
+        z.low &= ~ roundBitsMask;
+    }
+    else {
+        if ( aExp < 0x3FFF ) {
+            if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
+            float_set_inexact();
+            aSign = extractFloat128Sign( a );
+            switch ( float_rounding_mode() ) {
+             case float_round_nearest_even:
+                if (    ( aExp == 0x3FFE )
+                     && (   extractFloat128Frac0( a )
+                          | extractFloat128Frac1( a ) )
+                   ) {
+                    return packFloat128( aSign, 0x3FFF, 0, 0 );
+                }
+                break;
+             case float_round_down:
+                return
+                      aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
+                    : packFloat128( 0, 0, 0, 0 );
+             case float_round_up:
+                return
+                      aSign ? packFloat128( 1, 0, 0, 0 )
+                    : packFloat128( 0, 0x3FFF, 0, 0 );
+            }
+            return packFloat128( aSign, 0, 0, 0 );
+        }
+        lastBitMask = 1;
+        lastBitMask <<= 0x402F - aExp;
+        roundBitsMask = lastBitMask - 1;
+        z.low = 0;
+        z.high = a.high;
+        roundingMode = float_rounding_mode();
+        if ( roundingMode == float_round_nearest_even ) {
+            z.high += lastBitMask>>1;
+            if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
+                z.high &= ~ lastBitMask;
+            }
+        }
+        else if ( roundingMode != float_round_to_zero ) {
+            if (   extractFloat128Sign( z )
+                 ^ ( roundingMode == float_round_up ) ) {
+                z.high |= ( a.low != 0 );
+                z.high += roundBitsMask;
+            }
+        }
+        z.high &= ~ roundBitsMask;
+    }
+    if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the quadruple-precision
+floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
+before being returned.  `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128 addFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+    int32 aExp, bExp, zExp;
+    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+    int32 expDiff;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    bSig1 = extractFloat128Frac1( b );
+    bSig0 = extractFloat128Frac0( b );
+    bExp = extractFloat128Exp( b );
+    expDiff = aExp - bExp;
+    if ( 0 < expDiff ) {
+        if ( aExp == 0x7FFF ) {
+            if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+            return a;
+        }
+        if ( bExp == 0 ) {
+            --expDiff;
+        }
+        else {
+            bSig0 |= LIT64( 0x0001000000000000 );
+        }
+        shift128ExtraRightJamming(
+            bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
+        zExp = aExp;
+    }
+    else if ( expDiff < 0 ) {
+        if ( bExp == 0x7FFF ) {
+            if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+            return packFloat128( zSign, 0x7FFF, 0, 0 );
+        }
+        if ( aExp == 0 ) {
+            ++expDiff;
+        }
+        else {
+            aSig0 |= LIT64( 0x0001000000000000 );
+        }
+        shift128ExtraRightJamming(
+            aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
+        zExp = bExp;
+    }
+    else {
+        if ( aExp == 0x7FFF ) {
+            if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+                return propagateFloat128NaN( a, b );
+            }
+            return a;
+        }
+        add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+        if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 );
+        zSig2 = 0;
+        zSig0 |= LIT64( 0x0002000000000000 );
+        zExp = aExp;
+        goto shiftRight1;
+    }
+    aSig0 |= LIT64( 0x0001000000000000 );
+    add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+    --zExp;
+    if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
+    ++zExp;
+ shiftRight1:
+    shift128ExtraRightJamming(
+        zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ roundAndPack:
+    return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the quadruple-
+precision floating-point values `a' and `b'.  If `zSign' is 1, the
+difference is negated before being returned.  `zSign' is ignored if the
+result is a NaN.  The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128 subFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+    int32 aExp, bExp, zExp;
+    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
+    int32 expDiff;
+    float128 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    bSig1 = extractFloat128Frac1( b );
+    bSig0 = extractFloat128Frac0( b );
+    bExp = extractFloat128Exp( b );
+    expDiff = aExp - bExp;
+    shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
+    shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
+    if ( 0 < expDiff ) goto aExpBigger;
+    if ( expDiff < 0 ) goto bExpBigger;
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+            return propagateFloat128NaN( a, b );
+        }
+        float_raise( float_flag_invalid );
+        z.low = float128_default_nan_low;
+        z.high = float128_default_nan_high;
+        return z;
+    }
+    if ( aExp == 0 ) {
+        aExp = 1;
+        bExp = 1;
+    }
+    if ( bSig0 < aSig0 ) goto aBigger;
+    if ( aSig0 < bSig0 ) goto bBigger;
+    if ( bSig1 < aSig1 ) goto aBigger;
+    if ( aSig1 < bSig1 ) goto bBigger;
+    return packFloat128( float_rounding_mode() == float_round_down, 0, 0, 0 );
+ bExpBigger:
+    if ( bExp == 0x7FFF ) {
+        if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+        return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
+    }
+    if ( aExp == 0 ) {
+        ++expDiff;
+    }
+    else {
+        aSig0 |= LIT64( 0x4000000000000000 );
+    }
+    shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+    bSig0 |= LIT64( 0x4000000000000000 );
+ bBigger:
+    sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
+    zExp = bExp;
+    zSign ^= 1;
+    goto normalizeRoundAndPack;
+ aExpBigger:
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        --expDiff;
+    }
+    else {
+        bSig0 |= LIT64( 0x4000000000000000 );
+    }
+    shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
+    aSig0 |= LIT64( 0x4000000000000000 );
+ aBigger:
+    sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+    zExp = aExp;
+ normalizeRoundAndPack:
+    --zExp;
+    return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the quadruple-precision floating-point values
+`a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_add( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign == bSign ) {
+        return addFloat128Sigs( a, b, aSign );
+    }
+    else {
+        return subFloat128Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the quadruple-precision floating-point
+values `a' and `b'.  The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_sub( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign == bSign ) {
+        return subFloat128Sigs( a, b, aSign );
+    }
+    else {
+        return addFloat128Sigs( a, b, aSign );
+    }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the quadruple-precision floating-point
+values `a' and `b'.  The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_mul( float128 a, float128 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, zExp;
+    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
+    float128 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    bSig1 = extractFloat128Frac1( b );
+    bSig0 = extractFloat128Frac0( b );
+    bExp = extractFloat128Exp( b );
+    bSign = extractFloat128Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FFF ) {
+        if (    ( aSig0 | aSig1 )
+             || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
+            return propagateFloat128NaN( a, b );
+        }
+        if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
+        return packFloat128( zSign, 0x7FFF, 0, 0 );
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+        if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+            float_raise( float_flag_invalid );
+            z.low = float128_default_nan_low;
+            z.high = float128_default_nan_high;
+            return z;
+        }
+        return packFloat128( zSign, 0x7FFF, 0, 0 );
+    }
+    if ( aExp == 0 ) {
+        if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+    }
+    if ( bExp == 0 ) {
+        if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+    }
+    zExp = aExp + bExp - 0x4000;
+    aSig0 |= LIT64( 0x0001000000000000 );
+    shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
+    mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
+    add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
+    zSig2 |= ( zSig3 != 0 );
+    if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
+        shift128ExtraRightJamming(
+            zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+        ++zExp;
+    }
+    return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the quadruple-precision floating-point value
+`a' by the corresponding value `b'.  The operation is performed according to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_div( float128 a, float128 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, zExp;
+    bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    float128 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    bSig1 = extractFloat128Frac1( b );
+    bSig0 = extractFloat128Frac0( b );
+    bExp = extractFloat128Exp( b );
+    bSign = extractFloat128Sign( b );
+    zSign = aSign ^ bSign;
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+        if ( bExp == 0x7FFF ) {
+            if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+            goto invalid;
+        }
+        return packFloat128( zSign, 0x7FFF, 0, 0 );
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+        return packFloat128( zSign, 0, 0, 0 );
+    }
+    if ( bExp == 0 ) {
+        if ( ( bSig0 | bSig1 ) == 0 ) {
+            if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+                float_raise( float_flag_invalid );
+                z.low = float128_default_nan_low;
+                z.high = float128_default_nan_high;
+                return z;
+            }
+            float_raise( float_flag_divbyzero );
+            return packFloat128( zSign, 0x7FFF, 0, 0 );
+        }
+        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+    }
+    if ( aExp == 0 ) {
+        if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+    }
+    zExp = aExp - bExp + 0x3FFD;
+    shortShift128Left(
+        aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
+    shortShift128Left(
+        bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
+    if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
+        shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
+        ++zExp;
+    }
+    zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
+    mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
+    sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
+    while ( (sbits64) rem0 < 0 ) {
+        --zSig0;
+        add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
+    }
+    zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
+    if ( ( zSig1 & 0x3FFF ) <= 4 ) {
+        mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
+        sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
+        while ( (sbits64) rem1 < 0 ) {
+            --zSig1;
+            add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
+        }
+        zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+    }
+    shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
+    return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the quadruple-precision floating-point value `a'
+with respect to the corresponding value `b'.  The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_rem( float128 a, float128 b )
+{
+    flag aSign, bSign, zSign;
+    int32 aExp, bExp, expDiff;
+    bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
+    bits64 allZero, alternateASig0, alternateASig1, sigMean1;
+    sbits64 sigMean0;
+    float128 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    bSig1 = extractFloat128Frac1( b );
+    bSig0 = extractFloat128Frac0( b );
+    bExp = extractFloat128Exp( b );
+    bSign = extractFloat128Sign( b );
+    if ( aExp == 0x7FFF ) {
+        if (    ( aSig0 | aSig1 )
+             || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
+            return propagateFloat128NaN( a, b );
+        }
+        goto invalid;
+    }
+    if ( bExp == 0x7FFF ) {
+        if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+        return a;
+    }
+    if ( bExp == 0 ) {
+        if ( ( bSig0 | bSig1 ) == 0 ) {
+ invalid:
+            float_raise( float_flag_invalid );
+            z.low = float128_default_nan_low;
+            z.high = float128_default_nan_high;
+            return z;
+        }
+        normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+    }
+    if ( aExp == 0 ) {
+        if ( ( aSig0 | aSig1 ) == 0 ) return a;
+        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+    }
+    expDiff = aExp - bExp;
+    if ( expDiff < -1 ) return a;
+    shortShift128Left(
+        aSig0 | LIT64( 0x0001000000000000 ),
+        aSig1,
+        15 - ( expDiff < 0 ),
+        &aSig0,
+        &aSig1
+    );
+    shortShift128Left(
+        bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
+    q = le128( bSig0, bSig1, aSig0, aSig1 );
+    if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+    expDiff -= 64;
+    while ( 0 < expDiff ) {
+        q = estimateDiv128To64( aSig0, aSig1, bSig0 );
+        q = ( 4 < q ) ? q - 4 : 0;
+        mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
+        shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
+        shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
+        sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
+        expDiff -= 61;
+    }
+    if ( -64 < expDiff ) {
+        q = estimateDiv128To64( aSig0, aSig1, bSig0 );
+        q = ( 4 < q ) ? q - 4 : 0;
+        q >>= - expDiff;
+        shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
+        expDiff += 52;
+        if ( expDiff < 0 ) {
+            shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+        }
+        else {
+            shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
+        }
+        mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
+        sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
+    }
+    else {
+        shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
+        shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
+    }
+    do {
+        alternateASig0 = aSig0;
+        alternateASig1 = aSig1;
+        ++q;
+        sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+    } while ( 0 <= (sbits64) aSig0 );
+    add128(
+        aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
+    if (    ( sigMean0 < 0 )
+         || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
+        aSig0 = alternateASig0;
+        aSig1 = alternateASig1;
+    }
+    zSign = ( (sbits64) aSig0 < 0 );
+    if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
+    return
+        normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the quadruple-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_sqrt( float128 a )
+{
+    flag aSign;
+    int32 aExp, zExp;
+    bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
+    bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+    float128 z;
+
+    aSig1 = extractFloat128Frac1( a );
+    aSig0 = extractFloat128Frac0( a );
+    aExp = extractFloat128Exp( a );
+    aSign = extractFloat128Sign( a );
+    if ( aExp == 0x7FFF ) {
+        if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a );
+        if ( ! aSign ) return a;
+        goto invalid;
+    }
+    if ( aSign ) {
+        if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
+ invalid:
+        float_raise( float_flag_invalid );
+        z.low = float128_default_nan_low;
+        z.high = float128_default_nan_high;
+        return z;
+    }
+    if ( aExp == 0 ) {
+        if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
+        normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+    }
+    zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE;
+    aSig0 |= LIT64( 0x0001000000000000 );
+    zSig0 = estimateSqrt32( aExp, aSig0>>17 );
+    shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 );
+    zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
+    doubleZSig0 = zSig0<<1;
+    mul64To128( zSig0, zSig0, &term0, &term1 );
+    sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+    while ( (sbits64) rem0 < 0 ) {
+        --zSig0;
+        doubleZSig0 -= 2;
+        add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
+    }
+    zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
+    if ( ( zSig1 & 0x1FFF ) <= 5 ) {
+        if ( zSig1 == 0 ) zSig1 = 1;
+        mul64To128( doubleZSig0, zSig1, &term1, &term2 );
+        sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+        mul64To128( zSig1, zSig1, &term2, &term3 );
+        sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+        while ( (sbits64) rem1 < 0 ) {
+            --zSig1;
+            shortShift128Left( 0, zSig1, 1, &term2, &term3 );
+            term3 |= 1;
+            term2 |= doubleZSig0;
+            add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+        }
+        zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+    }
+    shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
+    return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_eq( float128 a, float128 b )
+{
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        if (    float128_is_signaling_nan( a )
+             || float128_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    return
+           ( a.low == b.low )
+        && (    ( a.high == b.high )
+             || (    ( a.low == 0 )
+                  && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+           );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise.  The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_le( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 == 0 );
+    }
+    return
+          aSign ? le128( b.high, b.low, a.high, a.low )
+        : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_lt( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 != 0 );
+    }
+    return
+          aSign ? lt128( b.high, b.low, a.high, a.low )
+        : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise.  The invalid exception is
+raised if either operand is a NaN.  Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_eq_signaling( float128 a, float128 b )
+{
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        float_raise( float_flag_invalid );
+        return 0;
+    }
+    return
+           ( a.low == b.low )
+        && (    ( a.high == b.high )
+             || (    ( a.low == 0 )
+                  && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+           );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
+cause an exception.  Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_le_quiet( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        if (    float128_is_signaling_nan( a )
+             || float128_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            || (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 == 0 );
+    }
+    return
+          aSign ? le128( b.high, b.low, a.high, a.low )
+        : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
+exception.  Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_lt_quiet( float128 a, float128 b )
+{
+    flag aSign, bSign;
+
+    if (    (    ( extractFloat128Exp( a ) == 0x7FFF )
+              && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+         || (    ( extractFloat128Exp( b ) == 0x7FFF )
+              && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+       ) {
+        if (    float128_is_signaling_nan( a )
+             || float128_is_signaling_nan( b ) ) {
+            float_raise( float_flag_invalid );
+        }
+        return 0;
+    }
+    aSign = extractFloat128Sign( a );
+    bSign = extractFloat128Sign( b );
+    if ( aSign != bSign ) {
+        return
+               aSign
+            && (    ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+                 != 0 );
+    }
+    return
+          aSign ? lt128( b.high, b.low, a.high, a.low )
+        : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+#endif
+
+
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+
+/*
+ * These two routines are not part of the original softfloat distribution.
+ *
+ * They are based on the corresponding conversions to integer but return
+ * unsigned numbers instead since these functions are required by GCC.
+ *
+ * Added by Mark Brinicombe <mark@NetBSD.org>  27/09/97
+ *
+ * float64 version overhauled for SoftFloat 2a [bjh21 2000-07-15]
+ */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit unsigned integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-point
+Arithmetic, except that the conversion is always rounded toward zero.  If
+`a' is a NaN, the largest positive integer is returned.  If the conversion
+overflows, the largest integer positive is returned.
+-------------------------------------------------------------------------------
+*/
+uint32 float64_to_uint32_round_to_zero( float64 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits64 aSig, savedASig;
+    uint32 z;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+
+    if (aSign) {
+        float_raise( float_flag_invalid );
+       return(0);
+    }
+
+    if ( 0x41E < aExp ) {
+        float_raise( float_flag_invalid );
+        return 0xffffffff;
+    }
+    else if ( aExp < 0x3FF ) {
+        if ( aExp || aSig ) float_set_inexact();
+        return 0;
+    }
+    aSig |= LIT64( 0x0010000000000000 );
+    shiftCount = 0x433 - aExp;
+    savedASig = aSig;
+    aSig >>= shiftCount;
+    z = aSig;
+    if ( ( aSig<<shiftCount ) != savedASig ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit unsigned integer format.  The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-point
+Arithmetic, except that the conversion is always rounded toward zero.  If
+`a' is a NaN, the largest positive integer is returned.  If the conversion
+overflows, the largest positive integer is returned.
+-------------------------------------------------------------------------------
+*/
+uint32 float32_to_uint32_round_to_zero( float32 a )
+{
+    flag aSign;
+    int16 aExp, shiftCount;
+    bits32 aSig;
+    uint32 z;
+
+    aSig = extractFloat32Frac( a );
+    aExp = extractFloat32Exp( a );
+    aSign = extractFloat32Sign( a );
+    shiftCount = aExp - 0x9E;
+
+    if (aSign) {
+        float_raise( float_flag_invalid );
+       return(0);
+    }
+    if ( 0 < shiftCount ) {
+        float_raise( float_flag_invalid );
+        return 0xFFFFFFFF;
+    }
+    else if ( aExp <= 0x7E ) {
+        if ( aExp | aSig ) float_set_inexact();
+        return 0;
+    }
+    aSig = ( aSig | 0x800000 )<<8;
+    z = aSig>>( - shiftCount );
+    if ( aSig<<( shiftCount & 31 ) ) {
+        float_set_inexact();
+    }
+    return z;
+
+}
+
+#endif
+
+#endif /* _STANDALONE */
diff --git a/sys/lib/libkern/softfloat.h b/sys/lib/libkern/softfloat.h
new file mode 100644 (file)
index 0000000..94637c9
--- /dev/null
@@ -0,0 +1,363 @@
+/* $NetBSD: softfloat.h,v 1.4 2008/04/28 20:24:06 martin Exp $ */
+
+/* This is a derivative work. */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ross Harvey.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser.  This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704.  Funding was partially provided by the
+National Science Foundation under grant MIP-9311980.  The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#include <sys/types.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <inttypes.h>
+#include <ieeefp.h>
+#else
+#include "sys/inttypes.h"
+#include "machine/ieeefp.h"
+#endif
+#include <sys/endian.h>
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'.  If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined.  The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+/* #define FLOATX80 */
+/* #define FLOAT128 */
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef u_int32_t float32;
+typedef u_int64_t float64;
+#ifdef FLOATX80
+typedef struct {
+#if BYTE_ORDER == BIG_ENDIAN
+    u_int16_t high;
+    u_int64_t low;
+#else
+    u_int64_t low;
+    u_int16_t high;
+#endif
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+    u_int64_t high, low;
+} float128;
+#endif
+
+/*
+ * Some of the global variables that used to be here have been removed for
+ * fairly obvious (defopt-MULTIPROCESSOR) reasons.  The rest (which don't
+ * change dynamically) will be removed later. [ross]
+ */
+
+#define float_rounding_mode() fpgetround()
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+
+extern int float_detect_tininess;
+enum {
+    float_tininess_after_rounding  = 1,
+    float_tininess_before_rounding = 0
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+
+enum {
+    float_round_nearest_even = FP_RN,
+    float_round_to_zero      = FP_RZ,
+    float_round_down         = FP_RM,
+    float_round_up           = FP_RP
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+
+enum {
+    float_flag_inexact   =  FP_X_IMP,
+    float_flag_underflow =  FP_X_UFL,
+    float_flag_overflow  =  FP_X_OFL,
+    float_flag_divbyzero =  FP_X_DZ,
+    float_flag_invalid   =  FP_X_INV
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int );
+float64 int32_to_float64( int );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( int );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( int );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
+float32 int64_to_float32( int64_t );
+float64 int64_to_float64( int64_t );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( int64_t );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( int64_t );
+#endif
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float32_to_int32( float32 );
+int float32_to_int32_round_to_zero( float32 );
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+int64_t float32_to_int64( float32 );
+int64_t float32_to_int64_round_to_zero( float32 );
+#endif
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+int float32_eq( float32, float32 );
+int float32_le( float32, float32 );
+int float32_lt( float32, float32 );
+int float32_eq_signaling( float32, float32 );
+int float32_le_quiet( float32, float32 );
+int float32_lt_quiet( float32, float32 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float32_is_signaling_nan( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float64_to_int32( float64 );
+int float64_to_int32_round_to_zero( float64 );
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+int64_t float64_to_int64( float64 );
+int64_t float64_to_int64_round_to_zero( float64 );
+#endif
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+#define float64_default_nan 0xFFF8000000000000LL
+
+static __inline int
+float64_is_nan(float64 a)
+{
+       return 0xFFE0000000000000LL < a << 1;
+}
+
+static __inline int
+float64_is_signaling_nan(float64 a)
+{
+       return (a >> 51 & 0xFFF) == 0xFFE && (a & 0x0007FFFFFFFFFFFFLL);
+}
+
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+int float64_eq( float64, float64 );
+int float64_le( float64, float64 );
+int float64_lt( float64, float64 );
+int float64_eq_signaling( float64, float64 );
+int float64_le_quiet( float64, float64 );
+int float64_lt_quiet( float64, float64 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float64_is_signaling_nan( float64 );
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int floatx80_to_int32( floatx80 );
+int floatx80_to_int32_round_to_zero( floatx80 );
+int64_t floatx80_to_int64( floatx80 );
+int64_t floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision.  Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern int floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+int floatx80_eq( floatx80, floatx80 );
+int floatx80_le( floatx80, floatx80 );
+int floatx80_lt( floatx80, floatx80 );
+int floatx80_eq_signaling( floatx80, floatx80 );
+int floatx80_le_quiet( floatx80, floatx80 );
+int floatx80_lt_quiet( floatx80, floatx80 );
+int floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float128_to_int32( float128 );
+int float128_to_int32_round_to_zero( float128 );
+int64_t float128_to_int64( float128 );
+int64_t float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+int float128_eq( float128, float128 );
+int float128_le( float128, float128 );
+int float128_lt( float128, float128 );
+int float128_eq_signaling( float128, float128 );
+int float128_le_quiet( float128, float128 );
+int float128_lt_quiet( float128, float128 );
+int float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/sys/lib/libkern/ulmax.c b/sys/lib/libkern/ulmax.c
new file mode 100644 (file)
index 0000000..61f81d2
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: ulmax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $    */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+unsigned long
+ulmax(unsigned long a, unsigned long b)
+{
+       return (a > b ? a : b);
+}
diff --git a/sys/lib/libkern/ulmin.c b/sys/lib/libkern/ulmin.c
new file mode 100644 (file)
index 0000000..c1afddd
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $NetBSD: ulmin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $    */
+
+/*
+ * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)subr_xxx.c  7.10 (Berkeley) 4/20/91
+ */
+
+#define LIBKERN_INLINE
+#include <lib/libkern/libkern.h>
+
+unsigned long
+ulmin(unsigned long a, unsigned long b)
+{
+       return (a < b ? a : b);
+}
diff --git a/sys/lib/libkern/xlat_mbr_fstype.c b/sys/lib/libkern/xlat_mbr_fstype.c
new file mode 100644 (file)
index 0000000..4151770
--- /dev/null
@@ -0,0 +1,66 @@
+/*     $NetBSD: xlat_mbr_fstype.c,v 1.7 2008/04/28 20:24:06 martin Exp $       */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David Laight.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0,"$NetBSD: xlat_mbr_fstype.c,v 1.7 2008/04/28 20:24:06 martin Exp $");
+
+
+#include <sys/disklabel.h>
+#include <sys/bootblock.h>
+
+int
+xlat_mbr_fstype(int mbr_type)
+{
+       static const struct ptn_types {
+               uint8_t mbr_type;
+               uint8_t netbsd_type;
+       } ptn_types[] = {
+               { MBR_PTYPE_386BSD,     FS_BSDFFS },
+               { MBR_PTYPE_APPLE_UFS,  FS_APPLEUFS },
+               { MBR_PTYPE_FAT12,      FS_MSDOS },
+               { MBR_PTYPE_FAT16B,     FS_MSDOS },
+               { MBR_PTYPE_FAT16L,     FS_MSDOS },
+               { MBR_PTYPE_FAT16S,     FS_MSDOS },
+               { MBR_PTYPE_FAT32,      FS_MSDOS },
+               { MBR_PTYPE_FAT32L,     FS_MSDOS },
+               { MBR_PTYPE_LNXEXT2,    FS_EX2FS },
+               { MBR_PTYPE_LNXSWAP,    FS_SWAP },
+               { MBR_PTYPE_NETBSD,     FS_BSDFFS },
+               { MBR_PTYPE_NTFS,       FS_NTFS },
+               { MBR_PTYPE_MINIX_14B,  FS_MINIXFS3 },
+               { 0,                    FS_OTHER }
+       };
+       const struct ptn_types *pt;
+       for (pt = ptn_types; pt->mbr_type != 0; pt++)
+               if (mbr_type == pt->mbr_type)
+                       break;
+       return pt->netbsd_type;
+}
diff --git a/sys/lib/libsa/Makefile b/sys/lib/libsa/Makefile
new file mode 100644 (file)
index 0000000..0eb99a7
--- /dev/null
@@ -0,0 +1,99 @@
+#      $NetBSD: Makefile,v 1.76 2011/12/25 06:09:08 tsutsui Exp $
+
+LIB=   sa
+NOPIC= # defined
+NOPROFILE=# defined
+
+SA_USE_CREAD?= no              # Read compressed kernels
+SA_INCLUDE_NET?= yes           # Netboot via TFTP, NFS
+SA_USE_LOADFILE?= no           # Generic executable loading support
+SA_ENABLE_LS_OP?= no           # Filesystems ls operation
+
+#DEBUGCPPFLAGS= -DBOOTP_DEBUG -DNETIF_DEBUG -DETHER_DEBUG -DNFS_DEBUG -DRPC_DEBUG -DRARP_DEBUG -DARP_DEBUG -DNET_DEBUG -DDEBUG -DPARANOID
+CPPFLAGS=      -I${SADIR} ${SACPPFLAGS} ${SAMISCCPPFLAGS} \
+               -DCOMPAT_UFS ${DEBUGCPPFLAGS}
+
+#COPTS+= -ansi -pedantic -Wall
+
+.if defined(SA_EXTRADIR)
+.-include "${SA_EXTRADIR}/Makefile.inc"
+.endif
+
+.include <bsd.own.mk>
+
+.PATH.c: ${SADIR} ${.PARSEDIR}/../../../common/lib/libc/string
+
+# stand routines
+SRCS+= alloc.c errno.c exit.c files.c \
+       getfile.c gets.c globals.c \
+       panic.c printf.c qsort.c snprintf.c sprintf.c strerror.c \
+       subr_prf.c twiddle.c vsprintf.c checkpasswd.c
+
+.if (${MACHINE_CPU} != "mips")
+SRCS+= exec.c
+.endif
+
+# string routines
+.if ${MACHINE_ARCH} != "i386" && ${MACHINE_ARCH} != "x86_64"
+SRCS+= memcmp.c memcpy.c memmove.c memset.c strchr.c
+.endif
+SRCS+= bcopy.c bzero.c # Remove me eventually.
+
+# io routines
+SRCS+= closeall.c dev.c disklabel.c dkcksum.c ioctl.c nullfs.c stat.c fstat.c
+SRCS+= close.c lseek.c open.c read.c write.c
+.if (${SA_USE_CREAD} == "yes")
+CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD
+SRCS+= cread.c
+.endif
+.if (${SA_ENABLE_LS_OP} == "yes")
+SRCS+= ls.c
+.endif
+
+.if (${SA_USE_LOADFILE} == "yes")
+SRCS+= loadfile.c loadfile_ecoff.c loadfile_elf32.c lookup_elf32.c \
+       loadfile_elf64.c lookup_elf64.c
+.if (${MACHINE_CPU} != "mips")
+SRCS+= loadfile_aout.c
+.endif
+.endif
+
+.if (${SA_INCLUDE_NET} == "yes")
+# network routines
+SRCS+= arp.c ether.c ether_sprintf.c ip_cksum.c net.c netif.c rpc.c udp.c ip.c
+
+# network info services:
+SRCS+= bootp.c rarp.c bootparam.c
+
+# boot filesystems
+SRCS+= nfs.c tftp.c
+.endif
+
+SRCS+= ffsv1.c ffsv2.c
+SRCS+= lfsv1.c lfsv2.c
+SRCS+= cd9660.c
+SRCS+= ustarfs.c
+SRCS+= dosfs.c
+SRCS+= ext2fs.c
+SRCS+= minixfs3.c
+# for historic compatibility ufs == ffsv1
+SRCS+= ufs.c
+
+# only needed during build
+libinstall::
+
+.undef DESTDIR
+.include <bsd.lib.mk>
+
+lib${LIB}.o:: ${OBJS}
+       @echo building standard ${LIB} library
+       @rm -f lib${LIB}.o
+       @${LD} -r -o lib${LIB}.o `lorder ${OBJS} | tsort`
+
+.if defined(HAVE_GCC) || defined(HAVE_PCC)
+CPPFLAGS+=     -Wno-pointer-sign
+.endif
+
+.if defined(HAVE_GCC) && ${HAVE_GCC} >= 45 && ${MACHINE_ARCH} == "vax"
+COPTS.bootp.c+=        -O0
+.endif
diff --git a/sys/lib/libsa/Makefile.inc b/sys/lib/libsa/Makefile.inc
new file mode 100644 (file)
index 0000000..de37c63
--- /dev/null
@@ -0,0 +1,87 @@
+#      $NetBSD: Makefile.inc,v 1.20 2011/05/26 12:56:31 joerg Exp $
+#
+#      Configuration variables (default values are below):
+#
+#      S       must be set to the top of the 'sys' tree.
+#      SADST   may be set to the location of the directory where library
+#              objects are to be built.  Defaults to ${.OBJDIR}/lib/sa.
+#      SA_AS   may be set to 'obj' to build a object from the library's
+#              object files.  (Otherwise, a library will be built.)
+#              Defaults to 'library'.
+#      SAMISCCPPFLAGS
+#              Miscellaneous cpp flags to be passed to the library's Makefile
+#              when building.
+#      SAMISCMAKEFLAGS
+#              Miscellaneous flags to be passed to the library's Makefile when
+#              building.  See library's Makefile for more details about
+#              supported flags and their default values.
+
+# Default values:
+SADST?=                ${.OBJDIR}/lib/sa
+SA_AS?=                library
+SADOTDIR?= ../../.
+
+CWARNFLAGS.clang+=     -Wno-format-extra-args
+
+SADIR=         ${S:S@^.@${SADOTDIR}@:Q}/lib/libsa
+.if (${SA_AS} == "obj")
+SALIB=         ${SADST}/libsa.o
+SALIB_PROF=    ${SADST}/libsa.po
+.else
+SALIB=         ${SADST}/libsa.a
+SALIB_PROF=    ${SADST}/libsa_p.a
+.endif
+ZLIBSRCDIR:=   ${.PARSEDIR}/../../../common/dist/zlib
+SAMISCCPPFLAGS+=-I${ZLIBSRCDIR}
+
+SAMAKE= \
+       cd ${SADST} && ${MAKE} -f ${SADIR:Q}/Makefile \
+           SADIR=${SADIR:Q} \
+           CC=${CC:Q} CFLAGS=${CFLAGS:Q} \
+           AS=${AS:Q} AFLAGS=${AFLAGS:Q} \
+           LORDER=${LORDER:Q} \
+           TSORT=${TSORT:Q} \
+           LD=${LD:Q} STRIP=${STRIP:Q} \
+           AR=${AR:Q} NM=${NM:Q} \
+           RANLIB=${RANLIB:Q} SIZE=${SIZE:Q} \
+           MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \
+           SACPPFLAGS=${CPPFLAGS:S@^-I.@-I${SADOTDIR}@g:Q} \
+           SAMISCCPPFLAGS=${SAMISCCPPFLAGS:Q} \
+           ${SAMISCMAKEFLAGS}
+
+${SALIB}:              .NOTMAIN .MAKE __always_make_salib
+       @echo making sure the sa library is up to date...
+.if (${SA_AS} == "library")
+       @${SAMAKE} libsa.a
+.else
+       @${SAMAKE} libsa.o
+.endif
+
+${SALIB_PROF}:         .NOTMAIN .MAKE __always_make_salib
+       @echo making sure the profiled sa library is up to date...
+.if (${SA_AS} == "library")
+       @${SAMAKE} libsa_p.a
+.else
+       @${SAMAKE} libsa.po
+.endif
+
+clean:                 .NOTMAIN cleansalib
+cleansalib:            .NOTMAIN
+       @echo cleaning the sa library objects
+       @if [ -d "${SADST}" ]; then ${SAMAKE} clean; fi
+
+cleandir distclean:    .NOTMAIN cleandirsalib
+cleandirsalib:         .NOTMAIN
+       @echo cleandiring the sa library objects
+       @if [ -d "${SADST}" ]; then ${SAMAKE} cleandir; fi
+
+dependall depend:      .NOTMAIN dependsalib
+dependsalib:           .NOTMAIN .MAKE __always_make_salib
+       @echo depending the sa library objects
+       @${SAMAKE} depend
+
+__always_make_salib:   .NOTMAIN
+       @mkdir -p ${SADST}
+
+.PHONY: __always_make_salib
+.PHONY: cleansalib cleandirsalib dependsalib
diff --git a/sys/lib/libsa/alloc.c b/sys/lib/libsa/alloc.c
new file mode 100644 (file)
index 0000000..a818542
--- /dev/null
@@ -0,0 +1,269 @@
+/*     $NetBSD: alloc.c,v 1.26 2011/07/30 03:43:20 jakllsch Exp $      */
+
+/*
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)alloc.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)alloc.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Dynamic memory allocator.
+ *
+ * Compile options:
+ *
+ *     ALLOC_TRACE     enable tracing of allocations/deallocations
+
+ *     ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than
+ *                     the default best-fit algorithm.
+ *
+ *     HEAP_LIMIT      heap limit address (defaults to "no limit").
+ *
+ *     HEAP_START      start address of heap (defaults to '&end').
+ *
+ *     DEBUG           enable debugging sanity checks.
+ */
+
+#include <sys/param.h>
+#include "stand.h"
+
+/*
+ * Each block actually has ALIGN(unsigned int) + ALIGN(size) bytes allocated
+ * to it, as follows:
+ *
+ * 0 ... (sizeof(unsigned int) - 1)
+ *     allocated or unallocated: holds size of user-data part of block.
+ *
+ * sizeof(unsigned int) ... (ALIGN(sizeof(unsigned int)) - 1)
+ *     allocated: unused
+ *     unallocated: depends on packing of struct fl
+ *
+ * ALIGN(sizeof(unsigned int)) ...
+ *     (ALIGN(sizeof(unsigned int)) + ALIGN(data size) - 1)
+ *     allocated: user data
+ *     unallocated: depends on packing of struct fl
+ *
+ * 'next' is only used when the block is unallocated (i.e. on the free list).
+ * However, note that ALIGN(sizeof(unsigned int)) + ALIGN(data size) must
+ * be at least 'sizeof(struct fl)', so that blocks can be used as structures
+ * when on the free list.
+ */
+struct fl {
+       unsigned int    size;
+       struct fl       *next;
+} *freelist;
+
+#ifdef HEAP_VARIABLE
+static char *top, *heapstart, *heaplimit;
+void
+setheap(void *start, void *limit)
+{
+       heapstart = top = start;
+       heaplimit = limit;
+}
+#define HEAP_START heapstart
+#define HEAP_LIMIT heaplimit
+#else /* !HEAP_VARIABLE */
+#ifndef HEAP_START
+extern char end[];
+#define HEAP_START end
+#endif
+static char *top = (char *)HEAP_START;
+#endif /* HEAP_VARIABLE */
+
+__compactcall void *
+alloc(size_t size)
+{
+       struct fl **f = &freelist, **bestf = NULL;
+#ifndef ALLOC_FIRST_FIT
+       unsigned int bestsize = 0xffffffff;     /* greater than any real size */
+#endif
+       char *help;
+       int failed;
+
+#ifdef ALLOC_TRACE
+       printf("alloc(%zu)", size);
+#endif
+
+#ifdef ALLOC_FIRST_FIT
+       while (*f != (struct fl *)0 && (size_t)(*f)->size < size)
+               f = &((*f)->next);
+       bestf = f;
+       failed = (*bestf == (struct fl *)0);
+#else
+       /* scan freelist */
+       while (*f) {
+               if ((size_t)(*f)->size >= size) {
+                       if ((size_t)(*f)->size == size) /* exact match */
+                               goto found;
+
+                       if ((*f)->size < bestsize) {
+                               /* keep best fit */
+                               bestf = f;
+                               bestsize = (*f)->size;
+                       }
+               }
+               f = &((*f)->next);
+       }
+
+       /* no match in freelist if bestsize unchanged */
+       failed = (bestsize == 0xffffffff);
+#endif
+
+       if (failed) { /* nothing found */
+               /*
+                * allocate from heap, keep chunk len in
+                * first word
+                */
+               help = top;
+
+               /* make _sure_ the region can hold a struct fl. */
+               if (size < ALIGN(sizeof (struct fl *)))
+                       size = ALIGN(sizeof (struct fl *));
+               top += ALIGN(sizeof(unsigned int)) + ALIGN(size);
+#ifdef HEAP_LIMIT
+               if (top > (char *)HEAP_LIMIT)
+                       panic("heap full (%p+%zu)", help, size);
+#endif
+               *(unsigned int *)(void *)help = (unsigned int)ALIGN(size);
+#ifdef ALLOC_TRACE
+               printf("=%lx\n", (u_long)help + ALIGN(sizeof(unsigned int)));
+#endif
+               return help + ALIGN(sizeof(unsigned int));
+       }
+
+       /* we take the best fit */
+       f = bestf;
+
+#ifndef ALLOC_FIRST_FIT
+found:
+#endif
+       /* remove from freelist */
+       help = (char *)(void *)*f;
+       *f = (*f)->next;
+#ifdef ALLOC_TRACE
+       printf("=%lx (origsize %u)\n",
+           (u_long)help + ALIGN(sizeof(unsigned int)), *(unsigned int *)help);
+#endif
+       return help + ALIGN(sizeof(unsigned int));
+}
+
+__compactcall void
+/*ARGSUSED*/
+dealloc(void *ptr, size_t size)
+{
+       struct fl *f =
+           (struct fl *)(void *)((char *)(void *)ptr -
+           ALIGN(sizeof(unsigned int)));
+#ifdef ALLOC_TRACE
+       printf("dealloc(%lx, %zu) (origsize %u)\n", (u_long)ptr, size, f->size);
+#endif
+#ifdef DEBUG
+       if (size > (size_t)f->size) {
+               printf("dealloc %zu bytes @%lx, should be <=%u\n",
+                       size, (u_long)ptr, f->size);
+       }
+
+       if (ptr < (void *)HEAP_START)
+               printf("dealloc: %lx before start of heap.\n", (u_long)ptr);
+
+#ifdef HEAP_LIMIT
+       if (ptr > (void *)HEAP_LIMIT)
+               printf("dealloc: %lx beyond end of heap.\n", (u_long)ptr);
+#endif
+#endif /* DEBUG */
+       /* put into freelist */
+       f->next = freelist;
+       freelist = f;
+}
diff --git a/sys/lib/libsa/arp.c b/sys/lib/libsa/arp.c
new file mode 100644 (file)
index 0000000..8716fd6
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: arp.c,v 1.33 2009/01/17 14:00:36 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <netinet/in.h>
+
+#include <netinet/in_systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "net.h"
+
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  Structure below is adapted
+ * to resolving internet addresses.  Field names used correspond to
+ * RFC 826.
+ */
+struct ether_arp {
+       struct   arphdr ea_hdr;                 /* fixed-size header */
+       u_int8_t arp_sha[ETHER_ADDR_LEN];       /* sender hardware address */
+       u_int8_t arp_spa[4];                    /* sender protocol address */
+       u_int8_t arp_tha[ETHER_ADDR_LEN];       /* target hardware address */
+       u_int8_t arp_tpa[4];                    /* target protocol address */
+};
+#define        arp_hrd ea_hdr.ar_hrd
+#define        arp_pro ea_hdr.ar_pro
+#define        arp_hln ea_hdr.ar_hln
+#define        arp_pln ea_hdr.ar_pln
+#define        arp_op  ea_hdr.ar_op
+
+/* Cache stuff */
+#define ARP_NUM 8                      /* need at most 3 arp entries */
+
+struct arp_list {
+       struct in_addr  addr;
+       u_char          ea[6];
+} arp_list[ARP_NUM] = {
+       /* XXX - net order `INADDR_BROADCAST' must be a constant */
+       { {0xffffffff}, BA }
+};
+int arp_num = 1;
+
+/* Local forwards */
+static ssize_t arpsend(struct iodesc *, void *, size_t);
+static ssize_t arprecv(struct iodesc *, void *, size_t, saseconds_t);
+
+/* Broadcast an ARP packet, asking who has addr on interface d */
+u_char *
+arpwhohas(struct iodesc *d, struct in_addr addr)
+{
+       int i;
+       struct ether_arp *ah;
+       struct arp_list *al;
+       struct {
+               struct ether_header eh;
+               struct {
+                       struct ether_arp arp;
+                       u_char pad[18];         /* 60 - sizeof(...) */
+               } data;
+       } wbuf;
+       struct {
+               struct ether_header eh;
+               struct {
+                       struct ether_arp arp;
+                       u_char pad[24];         /* extra space */
+               } data;
+       } rbuf;
+
+       /* Try for cached answer first */
+       for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
+               if (addr.s_addr == al->addr.s_addr)
+                       return al->ea;
+
+       /* Don't overflow cache */
+       if (arp_num > ARP_NUM - 1) {
+               arp_num = 1;    /* recycle */
+               printf("arpwhohas: overflowed arp_list!\n");
+       }
+
+#ifdef ARP_DEBUG
+       if (debug)
+               printf("arpwhohas: send request for %s\n", inet_ntoa(addr));
+#endif
+
+       (void)memset(&wbuf.data, 0, sizeof(wbuf.data));
+       ah = &wbuf.data.arp;
+       ah->arp_hrd = htons(ARPHRD_ETHER);
+       ah->arp_pro = htons(ETHERTYPE_IP);
+       ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */
+       ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */
+       ah->arp_op = htons(ARPOP_REQUEST);
+       MACPY(d->myea, ah->arp_sha);
+       (void)memcpy(ah->arp_spa, &d->myip, sizeof(ah->arp_spa));
+       /* Leave zeros in arp_tha */
+       (void)memcpy(ah->arp_tpa, &addr, sizeof(ah->arp_tpa));
+
+       /* Store ip address in cache (incomplete entry). */
+       al->addr = addr;
+
+       i = sendrecv(d,
+           arpsend, &wbuf.data, sizeof(wbuf.data),
+           arprecv, &rbuf.data, sizeof(rbuf.data));
+       if (i == -1) {
+               panic("arp: no response for %s",
+                         inet_ntoa(addr));
+       }
+
+       /* Store ethernet address in cache */
+       ah = &rbuf.data.arp;
+#ifdef ARP_DEBUG
+       if (debug) {
+               printf("arp: response from %s\n",
+                   ether_sprintf(rbuf.eh.ether_shost));
+               printf("arp: cacheing %s --> %s\n",
+                   inet_ntoa(addr), ether_sprintf(ah->arp_sha));
+       }
+#endif
+       MACPY(ah->arp_sha, al->ea);
+       ++arp_num;
+
+       return al->ea;
+}
+
+static ssize_t
+arpsend(struct iodesc *d, void *pkt, size_t len)
+{
+
+#ifdef ARP_DEBUG
+       if (debug)
+               printf("arpsend: called\n");
+#endif
+
+       return sendether(d, pkt, len, bcea, ETHERTYPE_ARP);
+}
+
+/*
+ * Returns 0 if this is the packet we're waiting for
+ * else -1 (and errno == 0)
+ */
+static ssize_t
+arprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       ssize_t n;
+       struct ether_arp *ah;
+       u_int16_t etype;        /* host order */
+
+#ifdef ARP_DEBUG
+       if (debug)
+               printf("arprecv: ");
+#endif
+
+       n = readether(d, pkt, len, tleft, &etype);
+       errno = 0;      /* XXX */
+       if (n == -1 || (size_t)n < sizeof(struct ether_arp)) {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("bad len=%ld\n", (signed long) n);
+#endif
+               return -1;
+       }
+
+       if (etype != ETHERTYPE_ARP) {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("not arp type=%d\n", etype);
+#endif
+               return -1;
+       }
+
+       /* Ethernet address now checked in readether() */
+
+       ah = (struct ether_arp *)pkt;
+       if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
+           ah->arp_pro != htons(ETHERTYPE_IP) ||
+           ah->arp_hln != sizeof(ah->arp_sha) ||
+           ah->arp_pln != sizeof(ah->arp_spa) )
+       {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("bad hrd/pro/hln/pln\n");
+#endif
+               return -1;
+       }
+
+       if (ah->arp_op == htons(ARPOP_REQUEST)) {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("is request\n");
+#endif
+               arp_reply(d, ah);
+               return -1;
+       }
+
+       if (ah->arp_op != htons(ARPOP_REPLY)) {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("not ARP reply\n");
+#endif
+               return -1;
+       }
+
+       /* Is the reply from the source we want? */
+       if (memcmp(&arp_list[arp_num].addr,
+                        ah->arp_spa, sizeof(ah->arp_spa)))
+       {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("unwanted address\n");
+#endif
+               return -1;
+       }
+       /* We don't care who the reply was sent to. */
+
+       /* We have our answer. */
+#ifdef ARP_DEBUG
+       if (debug)
+               printf("got it\n");
+#endif
+       return n;
+}
+
+/*
+ * Convert an ARP request into a reply and send it.
+ * Notes:  Re-uses buffer.  Pad to length = 46.
+ */
+void
+arp_reply(struct iodesc *d, void *pkt)
+{
+       struct ether_arp *arp = pkt;
+
+       if (arp->arp_hrd != htons(ARPHRD_ETHER) ||
+           arp->arp_pro != htons(ETHERTYPE_IP) ||
+           arp->arp_hln != sizeof(arp->arp_sha) ||
+           arp->arp_pln != sizeof(arp->arp_spa) )
+       {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("arp_reply: bad hrd/pro/hln/pln\n");
+#endif
+               return;
+       }
+
+       if (arp->arp_op != htons(ARPOP_REQUEST)) {
+#ifdef ARP_DEBUG
+               if (debug)
+                       printf("arp_reply: not request!\n");
+#endif
+               return;
+       }
+
+       /* If we are not the target, ignore the request. */
+       if (memcmp(arp->arp_tpa, &d->myip, sizeof(arp->arp_tpa)))
+               return;
+
+#ifdef ARP_DEBUG
+       if (debug) {
+               printf("arp_reply: to %s\n", ether_sprintf(arp->arp_sha));
+       }
+#endif
+
+       arp->arp_op = htons(ARPOP_REPLY);
+       /* source becomes target */
+       (void)memcpy(arp->arp_tha, arp->arp_sha, sizeof(arp->arp_tha));
+       (void)memcpy(arp->arp_tpa, arp->arp_spa, sizeof(arp->arp_tpa));
+       /* here becomes source */
+       (void)memcpy(arp->arp_sha, d->myea, sizeof(arp->arp_sha));
+       (void)memcpy(arp->arp_spa, &d->myip, sizeof(arp->arp_spa));
+
+       /*
+        * No need to get fancy here.  If the send fails, the
+        * requestor will just ask again.
+        */
+       (void) sendether(d, pkt, sizeof(*arp) + 18,
+                        arp->arp_tha, ETHERTYPE_ARP);
+}
diff --git a/sys/lib/libsa/bootp.c b/sys/lib/libsa/bootp.c
new file mode 100644 (file)
index 0000000..c7c9afe
--- /dev/null
@@ -0,0 +1,447 @@
+/*     $NetBSD: bootp.c,v 1.38 2011/05/11 16:23:40 zoltan Exp $        */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp  (LBL)
+ */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "net.h"
+#include "bootp.h"
+
+struct in_addr servip;
+#ifdef SUPPORT_LINUX
+char linuxcmdline[256];
+#ifndef TAG_LINUX_CMDLINE
+#define TAG_LINUX_CMDLINE 123
+#endif
+#endif
+
+static n_long  nmask, smask;
+
+static satime_t        bot;
+
+static char vm_rfc1048[4] = VM_RFC1048;
+#ifdef BOOTP_VEND_CMU
+static char vm_cmu[4] = VM_CMU;
+#endif
+
+/* Local forwards */
+static ssize_t bootpsend(struct iodesc *, void *, size_t);
+static ssize_t bootprecv(struct iodesc *, void *, size_t, saseconds_t);
+static int vend_rfc1048(u_char *, u_int);
+#ifdef BOOTP_VEND_CMU
+static void vend_cmu(u_char *);
+#endif
+
+#ifdef SUPPORT_DHCP
+static char expected_dhcpmsgtype = -1, dhcp_ok;
+struct in_addr dhcp_serverip;
+#endif
+
+/*
+ * Boot programs can patch this at run-time to change the behavior
+ * of bootp/dhcp.
+ */
+int bootp_flags;
+
+static void
+bootp_addvend(u_char *area)
+{
+#ifdef SUPPORT_DHCP
+       char vci[64];
+       int vcilen;
+       
+       *area++ = TAG_PARAM_REQ;
+       *area++ = 6;
+       *area++ = TAG_SUBNET_MASK;
+       *area++ = TAG_GATEWAY;
+       *area++ = TAG_HOSTNAME;
+       *area++ = TAG_DOMAINNAME;
+       *area++ = TAG_ROOTPATH;
+       *area++ = TAG_SWAPSERVER;
+
+       /* Insert a NetBSD Vendor Class Identifier option. */
+       sprintf(vci, "NetBSD:%s:libsa", MACHINE);
+       vcilen = strlen(vci);
+       *area++ = TAG_CLASSID;
+       *area++ = vcilen;
+       (void)memcpy(area, vci, vcilen);
+       area += vcilen;
+#endif
+       *area = TAG_END;
+}
+
+/* Fetch required bootp information */
+void
+bootp(int sock)
+{
+       struct iodesc *d;
+       struct bootp *bp;
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct bootp wbootp;
+       } wbuf;
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct bootp rbootp;
+       } rbuf;
+       unsigned int index;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootp: socket=%d\n", sock);
+#endif
+       if (!bot)
+               bot = getsecs();
+
+       if (!(d = socktodesc(sock))) {
+               printf("bootp: bad socket. %d\n", sock);
+               return;
+       }
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootp: d=%lx\n", (long)d);
+#endif
+
+       bp = &wbuf.wbootp;
+       (void)memset(bp, 0, sizeof(*bp));
+
+       bp->bp_op = BOOTREQUEST;
+       bp->bp_htype = 1;               /* 10Mb Ethernet (48 bits) */
+       bp->bp_hlen = 6;
+       bp->bp_xid = htonl(d->xid);
+       MACPY(d->myea, bp->bp_chaddr);
+       (void)strncpy((char *)bp->bp_file, bootfile, sizeof(bp->bp_file));
+       (void)memcpy(bp->bp_vend, vm_rfc1048, sizeof(vm_rfc1048));
+       index = 4;
+#ifdef SUPPORT_DHCP
+       bp->bp_vend[index++] = TAG_DHCP_MSGTYPE;
+       bp->bp_vend[index++] = 1;
+       bp->bp_vend[index++] = DHCPDISCOVER;
+#endif
+       bootp_addvend(&bp->bp_vend[index]);
+
+       d->myip.s_addr = INADDR_ANY;
+       d->myport = htons(IPPORT_BOOTPC);
+       d->destip.s_addr = INADDR_BROADCAST;
+       d->destport = htons(IPPORT_BOOTPS);
+
+#ifdef SUPPORT_DHCP
+       expected_dhcpmsgtype = DHCPOFFER;
+       dhcp_ok = 0;
+#endif
+
+       if (sendrecv(d,
+                   bootpsend, bp, sizeof(*bp),
+                   bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
+          == -1) {
+               printf("bootp: no reply\n");
+               return;
+       }
+
+#ifdef SUPPORT_DHCP
+       if (dhcp_ok) {
+               u_int32_t leasetime;
+               index = 6;
+               bp->bp_vend[index++] = DHCPREQUEST;
+               bp->bp_vend[index++] = TAG_REQ_ADDR;
+               bp->bp_vend[index++] = 4;
+               (void)memcpy(&bp->bp_vend[9], &rbuf.rbootp.bp_yiaddr, 4);
+               index += 4;
+               bp->bp_vend[index++] = TAG_SERVERID;
+               bp->bp_vend[index++] = 4;
+               (void)memcpy(&bp->bp_vend[index], &dhcp_serverip.s_addr, 4);
+               index += 4;
+               bp->bp_vend[index++] = TAG_LEASETIME;
+               bp->bp_vend[index++] = 4;
+               leasetime = htonl(300);
+               (void)memcpy(&bp->bp_vend[index], &leasetime, 4);
+               index += 4;
+               bootp_addvend(&bp->bp_vend[index]);
+
+               expected_dhcpmsgtype = DHCPACK;
+
+               if (sendrecv(d,
+                           bootpsend, bp, sizeof(*bp),
+                           bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
+                  == -1) {
+                       printf("DHCPREQUEST failed\n");
+                       return;
+               }
+       }
+#endif
+
+       myip = d->myip = rbuf.rbootp.bp_yiaddr;
+       servip = rbuf.rbootp.bp_siaddr;
+       if (rootip.s_addr == INADDR_ANY)
+               rootip = servip;
+       (void)memcpy(bootfile, rbuf.rbootp.bp_file, sizeof(bootfile));
+       bootfile[sizeof(bootfile) - 1] = '\0';
+
+       if (IN_CLASSA(myip.s_addr))
+               nmask = IN_CLASSA_NET;
+       else if (IN_CLASSB(myip.s_addr))
+               nmask = IN_CLASSB_NET;
+       else
+               nmask = IN_CLASSC_NET;
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("'native netmask' is %s\n", intoa(nmask));
+#endif
+
+       /* Get subnet (or natural net) mask */
+       netmask = nmask;
+       if (smask)
+               netmask = smask;
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("mask: %s\n", intoa(netmask));
+#endif
+
+       /* We need a gateway if root is on a different net */
+       if (!SAMENET(myip, rootip, netmask)) {
+#ifdef BOOTP_DEBUG
+               if (debug)
+                       printf("need gateway for root ip\n");
+#endif
+       }
+
+       /* Toss gateway if on a different net */
+       if (!SAMENET(myip, gateip, netmask)) {
+#ifdef BOOTP_DEBUG
+               if (debug)
+                       printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
+#endif
+               gateip.s_addr = 0;
+       }
+
+#ifdef BOOTP_DEBUG
+       if (debug) {
+               printf("client addr: %s\n", inet_ntoa(myip));
+               if (smask)
+                       printf("subnet mask: %s\n", intoa(smask));
+               if (gateip.s_addr != 0)
+                       printf("net gateway: %s\n", inet_ntoa(gateip));
+               printf("server addr: %s\n", inet_ntoa(rootip));
+               if (rootpath[0] != '\0')
+                       printf("server path: %s\n", rootpath);
+               if (bootfile[0] != '\0')
+                       printf("file name: %s\n", bootfile);
+       }
+#endif
+
+       /* Bump xid so next request will be unique. */
+       ++d->xid;
+}
+
+/* Transmit a bootp request */
+static ssize_t
+bootpsend(struct iodesc *d, void *pkt, size_t len)
+{
+       struct bootp *bp;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootpsend: d=%lx called.\n", (long)d);
+#endif
+
+       bp = pkt;
+       bp->bp_secs = htons((u_short)(getsecs() - bot));
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootpsend: calling sendudp\n");
+#endif
+
+       return sendudp(d, pkt, len);
+}
+
+static ssize_t
+bootprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       ssize_t n;
+       struct bootp *bp;
+
+#ifdef BOOTP_DEBUGx
+       if (debug)
+               printf("bootp_recvoffer: called\n");
+#endif
+
+       n = readudp(d, pkt, len, tleft);
+       if (n == -1 || (size_t)n < sizeof(struct bootp) - BOOTP_VENDSIZE)
+               goto bad;
+
+       bp = (struct bootp *)pkt;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootprecv: checked.  bp = 0x%lx, n = %d\n",
+                   (long)bp, (int)n);
+#endif
+       if (bp->bp_xid != htonl(d->xid)) {
+#ifdef BOOTP_DEBUG
+               if (debug) {
+                       printf("bootprecv: expected xid 0x%lx, got 0x%x\n",
+                           d->xid, ntohl(bp->bp_xid));
+               }
+#endif
+               goto bad;
+       }
+
+       /* protect against bogus addresses sent by DHCP servers */
+       if (bp->bp_yiaddr.s_addr == INADDR_ANY ||
+           bp->bp_yiaddr.s_addr == INADDR_BROADCAST)
+               goto bad;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("bootprecv: got one!\n");
+#endif
+
+       /* Suck out vendor info */
+       if (memcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
+               if (vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0)
+                       goto bad;
+       }
+#ifdef BOOTP_VEND_CMU
+       else if (memcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
+               vend_cmu(bp->bp_vend);
+#endif
+       else
+               printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
+
+       return n;
+bad:
+       errno = 0;
+       return -1;
+}
+
+static int
+vend_rfc1048(u_char *cp, u_int len)
+{
+       u_char *ep;
+       int size;
+       u_char tag;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("vend_rfc1048 bootp info. len=%d\n", len);
+#endif
+       ep = cp + len;
+
+       /* Step over magic cookie */
+       cp += sizeof(int);
+
+       while (cp < ep) {
+               tag = *cp++;
+               size = *cp++;
+               if (tag == TAG_END)
+                       break;
+
+               if (tag == TAG_SUBNET_MASK && size >= sizeof(smask)) {
+                       (void)memcpy(&smask, cp, sizeof(smask));
+               }
+               if (tag == TAG_GATEWAY && size >= sizeof(gateip.s_addr)) {
+                       (void)memcpy(&gateip.s_addr, cp, sizeof(gateip.s_addr));
+               }
+               if (tag == TAG_SWAPSERVER && size >= sizeof(rootip.s_addr)) {
+                       /* let it override bp_siaddr */
+                       (void)memcpy(&rootip.s_addr, cp, sizeof(rootip.s_addr));
+               }
+               if (tag == TAG_ROOTPATH && size < sizeof(rootpath)) {
+                       strncpy(rootpath, (char *)cp, sizeof(rootpath));
+                       rootpath[size] = '\0';
+               }
+               if (tag == TAG_HOSTNAME && size < sizeof(hostname)) {
+                       strncpy(hostname, (char *)cp, sizeof(hostname));
+                       hostname[size] = '\0';
+               }
+#ifdef SUPPORT_DHCP
+               if (tag == TAG_DHCP_MSGTYPE) {
+                       if (*cp != expected_dhcpmsgtype)
+                               return -1;
+                       dhcp_ok = 1;
+               }
+               if (tag == TAG_SERVERID &&
+                   size >= sizeof(dhcp_serverip.s_addr))
+               {
+                       (void)memcpy(&dhcp_serverip.s_addr, cp, 
+                             sizeof(dhcp_serverip.s_addr));
+               }
+#endif
+#ifdef SUPPORT_LINUX
+               if (tag == TAG_LINUX_CMDLINE && size < sizeof(linuxcmdline)) {
+                       strncpy(linuxcmdline, (char *)cp, sizeof(linuxcmdline));
+                       linuxcmdline[size] = '\0';
+               }
+#endif
+               cp += size;
+       }
+       return 0;
+}
+
+#ifdef BOOTP_VEND_CMU
+static void
+vend_cmu(u_char *cp)
+{
+       struct cmu_vend *vp;
+
+#ifdef BOOTP_DEBUG
+       if (debug)
+               printf("vend_cmu bootp info.\n");
+#endif
+       vp = (struct cmu_vend *)cp;
+
+       if (vp->v_smask.s_addr != 0) {
+               smask = vp->v_smask.s_addr;
+       }
+       if (vp->v_dgate.s_addr != 0) {
+               gateip = vp->v_dgate;
+       }
+}
+#endif
diff --git a/sys/lib/libsa/bootp.h b/sys/lib/libsa/bootp.h
new file mode 100644 (file)
index 0000000..50fadca
--- /dev/null
@@ -0,0 +1,138 @@
+/*     $NetBSD: bootp.h,v 1.9 2009/01/17 14:00:36 tsutsui Exp $        */
+
+/*
+ * Bootstrap Protocol (BOOTP).  RFC951 and RFC1048.
+ *
+ * This file specifies the "implementation-independent" BOOTP protocol
+ * information which is common to both client and server.
+ *
+ * Copyright 1988 by Carnegie Mellon.
+ *
+ * Permission to use, copy, modify, and distribute this program for any
+ * purpose and without fee is hereby granted, provided that this copyright
+ * and permission notice appear on all copies and supporting documentation,
+ * the name of Carnegie Mellon not be used in advertising or publicity
+ * pertaining to distribution of the program without specific prior
+ * permission, and notice be given in supporting documentation that copying
+ * and distribution is by permission of Carnegie Mellon and Stanford
+ * University.  Carnegie Mellon makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ */
+
+
+struct bootp {
+       unsigned char   bp_op;          /* packet opcode type */
+       unsigned char   bp_htype;       /* hardware addr type */
+       unsigned char   bp_hlen;        /* hardware addr length */
+       unsigned char   bp_hops;        /* gateway hops */
+       unsigned int    bp_xid;         /* transaction ID */
+       unsigned short  bp_secs;        /* seconds since boot began */
+       unsigned short  bp_flags;
+       struct in_addr  bp_ciaddr;      /* client IP address */
+       struct in_addr  bp_yiaddr;      /* 'your' IP address */
+       struct in_addr  bp_siaddr;      /* server IP address */
+       struct in_addr  bp_giaddr;      /* gateway IP address */
+       unsigned char   bp_chaddr[16];  /* client hardware address */
+       unsigned char   bp_sname[64];   /* server host name */
+       unsigned char   bp_file[128];   /* boot file name */
+#ifdef SUPPORT_DHCP
+#define BOOTP_VENDSIZE 312
+#else
+#define BOOTP_VENDSIZE 64
+#endif
+       unsigned char   bp_vend[BOOTP_VENDSIZE]; /* vendor-specific area */
+};
+
+/*
+ * UDP port numbers, server and client.
+ */
+#define        IPPORT_BOOTPS           67
+#define        IPPORT_BOOTPC           68
+
+#define BOOTREPLY              2
+#define BOOTREQUEST            1
+
+
+/*
+ * Vendor magic cookie (v_magic) for CMU
+ */
+#define VM_CMU         "CMU"
+
+/*
+ * Vendor magic cookie (v_magic) for RFC1048
+ */
+#define VM_RFC1048     { 99, 130, 83, 99 }
+
+
+/*
+ * RFC1048 tag values used to specify what information is being supplied in
+ * the vendor field of the packet.
+ */
+
+#define TAG_PAD                        ((unsigned char)   0)
+#define TAG_SUBNET_MASK                ((unsigned char)   1)
+#define TAG_TIME_OFFSET                ((unsigned char)   2)
+#define TAG_GATEWAY            ((unsigned char)   3)
+#define TAG_TIME_SERVER                ((unsigned char)   4)
+#define TAG_NAME_SERVER                ((unsigned char)   5)
+#define TAG_DOMAIN_SERVER      ((unsigned char)   6)
+#define TAG_LOG_SERVER         ((unsigned char)   7)
+#define TAG_COOKIE_SERVER      ((unsigned char)   8)
+#define TAG_LPR_SERVER         ((unsigned char)   9)
+#define TAG_IMPRESS_SERVER     ((unsigned char)  10)
+#define TAG_RLP_SERVER         ((unsigned char)  11)
+#define TAG_HOSTNAME           ((unsigned char)  12)
+#define TAG_BOOTSIZE           ((unsigned char)  13)
+#define TAG_DUMPFILE           ((unsigned char)  14)
+#define TAG_DOMAINNAME         ((unsigned char)  15)
+#define TAG_SWAPSERVER         ((unsigned char)  16)
+#define TAG_ROOTPATH           ((unsigned char)  17)
+
+#ifdef SUPPORT_DHCP
+#define TAG_REQ_ADDR           ((unsigned char)  50)
+#define TAG_LEASETIME          ((unsigned char)  51)
+#define TAG_OVERLOAD           ((unsigned char)  52)
+#define TAG_DHCP_MSGTYPE       ((unsigned char)  53)
+#define TAG_SERVERID           ((unsigned char)  54)
+#define TAG_PARAM_REQ          ((unsigned char)  55)
+#define TAG_MSG                        ((unsigned char)  56)
+#define TAG_MAXSIZE            ((unsigned char)  57)
+#define TAG_T1                 ((unsigned char)  58)
+#define TAG_T2                 ((unsigned char)  59)
+#define TAG_CLASSID            ((unsigned char)  60)
+#define TAG_CLIENTID           ((unsigned char)  61)
+#endif
+
+#define TAG_END                        ((unsigned char) 255)
+
+#ifdef SUPPORT_DHCP
+#define DHCPDISCOVER   1
+#define DHCPOFFER      2
+#define DHCPREQUEST    3
+#define DHCPDECLINE    4
+#define DHCPACK                5
+#define DHCPNAK                6
+#define DHCPRELEASE    7
+#endif
+
+/*
+ * "vendor" data permitted for CMU bootp clients.
+ */
+
+struct cmu_vend {
+       unsigned char   v_magic[4];     /* magic number */
+       unsigned int    v_flags;        /* flags/opcodes, etc. */
+       struct in_addr  v_smask;        /* Subnet mask */
+       struct in_addr  v_dgate;        /* Default gateway */
+       struct in_addr  v_dns1, v_dns2; /* Domain name servers */
+       struct in_addr  v_ins1, v_ins2; /* IEN-116 name servers */
+       struct in_addr  v_ts1, v_ts2;   /* Time servers */
+       unsigned char   v_unused[25];   /* currently unused */
+};
+
+
+/* v_flags values */
+#define VF_SMASK       1       /* Subnet mask field contains valid data */
+
+extern void    bootp(int);
diff --git a/sys/lib/libsa/bootparam.c b/sys/lib/libsa/bootparam.c
new file mode 100644 (file)
index 0000000..8c6b918
--- /dev/null
@@ -0,0 +1,439 @@
+/*     $NetBSD: bootparam.c,v 1.19 2009/10/21 23:12:10 snj Exp $       */
+
+/*
+ * Copyright (c) 1995 Gordon W. Ross
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * RPC/bootparams
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "rpcv2.h"
+
+#include "stand.h"
+#include "net.h"
+#include "rpc.h"
+#include "bootparam.h"
+
+#ifdef DEBUG_RPC
+#define RPC_PRINTF(a)  printf a
+#else
+#define RPC_PRINTF(a)
+#endif
+
+struct in_addr bp_server_addr; /* net order */
+n_short                bp_server_port; /* net order */
+
+int            hostnamelen;
+char           domainname[FNAME_SIZE]; /* our DNS domain */
+int            domainnamelen;
+
+/*
+ * RPC definitions for bootparamd
+ */
+#define        BOOTPARAM_PROG          100026
+#define        BOOTPARAM_VERS          1
+#define BOOTPARAM_WHOAMI       1
+#define BOOTPARAM_GETFILE      2
+
+/*
+ * Inet address in RPC messages
+ * (Note, really four ints, NOT chars.  Blech.)
+ */
+struct xdr_inaddr {
+       u_int32_t  atype;
+       int32_t addr[4];
+};
+
+int xdr_inaddr_encode(char **, struct in_addr);
+int xdr_inaddr_decode(char **, struct in_addr *);
+
+int xdr_string_encode(char **, char *, int);
+int xdr_string_decode(char **, char *, int *);
+
+
+/*
+ * RPC: bootparam/whoami
+ * Given client IP address, get:
+ *     client name     (hostname)
+ *     domain name (domainname)
+ *     gateway address
+ *
+ * The hostname and domainname are set here for convenience.
+ *
+ * Note - bpsin is initialized to the broadcast address,
+ * and will be replaced with the bootparam server address
+ * after this call is complete.  Have to use PMAP_PROC_CALL
+ * to make sure we get responses only from a servers that
+ * know about us (don't want to broadcast a getport call).
+ */
+int
+bp_whoami(int sockfd)
+{
+       /* RPC structures for PMAPPROC_CALLIT */
+       struct args {
+               u_int32_t prog;
+               u_int32_t vers;
+               u_int32_t proc;
+               u_int32_t arglen;
+               struct xdr_inaddr xina;
+       } *args;
+       struct repl {
+               u_int16_t _pad;
+               u_int16_t port;
+               u_int32_t encap_len;
+               /* encapsulated data here */
+               n_long  capsule[64];
+       } *repl;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct args d;
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct repl d;
+       } rdata;
+       char *send_tail, *recv_head;
+       struct iodesc *d;
+       int len, x;
+
+       RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
+
+       if (!(d = socktodesc(sockfd))) {
+               RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
+               return -1;
+       }
+       args = &sdata.d;
+       repl = &rdata.d;
+
+       /*
+        * Build request args for PMAPPROC_CALLIT.
+        */
+       args->prog = htonl(BOOTPARAM_PROG);
+       args->vers = htonl(BOOTPARAM_VERS);
+       args->proc = htonl(BOOTPARAM_WHOAMI);
+       args->arglen = htonl(sizeof(struct xdr_inaddr));
+       send_tail = (char *)&args->xina;
+
+       /*
+        * append encapsulated data (client IP address)
+        */
+       if (xdr_inaddr_encode(&send_tail, myip))
+               return -1;
+
+       /* RPC: portmap/callit */
+       d->myport = htons(--rpc_port);
+       d->destip.s_addr = INADDR_BROADCAST;    /* XXX: subnet bcast? */
+       /* rpc_call will set d->destport */
+
+       len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
+                                 args, send_tail - (char *)args,
+                                 repl, sizeof(*repl));
+       if (len < 8) {
+               printf("bootparamd: 'whoami' call failed\n");
+               return -1;
+       }
+
+       /* Save bootparam server address (from IP header). */
+       rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
+
+       /*
+        * Note that bp_server_port is now 111 due to the
+        * indirect call (using PMAPPROC_CALLIT), so get the
+        * actual port number from the reply data.
+        */
+       bp_server_port = repl->port;
+
+       RPC_PRINTF(("bp_whoami: server at %s:%d\n",
+           inet_ntoa(bp_server_addr), ntohs(bp_server_port)));
+
+       /* We have just done a portmap call, so cache the portnum. */
+       rpc_pmap_putcache(bp_server_addr,
+                         BOOTPARAM_PROG,
+                         BOOTPARAM_VERS,
+                         (int)ntohs(bp_server_port));
+
+       /*
+        * Parse the encapsulated results from bootparam/whoami
+        */
+       x = ntohl(repl->encap_len);
+       if (len < x) {
+               printf("bp_whoami: short reply, %d < %d\n", len, x);
+               return -1;
+       }
+       recv_head = (char *)repl->capsule;
+
+       /* client name */
+       hostnamelen = MAXHOSTNAMELEN-1;
+       if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
+               RPC_PRINTF(("bp_whoami: bad hostname\n"));
+               return -1;
+       }
+
+       /* domain name */
+       domainnamelen = MAXHOSTNAMELEN-1;
+       if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
+               RPC_PRINTF(("bp_whoami: bad domainname\n"));
+               return -1;
+       }
+
+       /* gateway address */
+       if (xdr_inaddr_decode(&recv_head, &gateip)) {
+               RPC_PRINTF(("bp_whoami: bad gateway\n"));
+               return -1;
+       }
+
+       /* success */
+       return 0;
+}
+
+
+/*
+ * RPC: bootparam/getfile
+ * Given client name and file "key", get:
+ *     server name
+ *     server IP address
+ *     server pathname
+ */
+int
+bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
+{
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               n_long  d[64];
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               n_long  d[128];
+       } rdata;
+       char serv_name[FNAME_SIZE];
+       char *send_tail, *recv_head;
+       /* misc... */
+       struct iodesc *d;
+       int sn_len, path_len, rlen;
+
+       if (!(d = socktodesc(sockfd))) {
+               RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
+               return -1;
+       }
+
+       send_tail = (char *)sdata.d;
+       recv_head = (char *)rdata.d;
+
+       /*
+        * Build request message.
+        */
+
+       /* client name (hostname) */
+       if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
+               RPC_PRINTF(("bp_getfile: bad client\n"));
+               return -1;
+       }
+
+       /* key name (root or swap) */
+       if (xdr_string_encode(&send_tail, key, strlen(key))) {
+               RPC_PRINTF(("bp_getfile: bad key\n"));
+               return -1;
+       }
+
+       /* RPC: bootparam/getfile */
+       d->myport = htons(--rpc_port);
+       d->destip = bp_server_addr;
+       /* rpc_call will set d->destport */
+
+       rlen = rpc_call(d,
+               BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
+               sdata.d, send_tail - (char *)sdata.d,
+               rdata.d, sizeof(rdata.d));
+       if (rlen < 4) {
+               RPC_PRINTF(("bp_getfile: short reply\n"));
+               errno = EBADRPC;
+               return -1;
+       }
+       recv_head = (char *)rdata.d;
+
+       /*
+        * Parse result message.
+        */
+
+       /* server name */
+       sn_len = FNAME_SIZE-1;
+       if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
+               RPC_PRINTF(("bp_getfile: bad server name\n"));
+               return -1;
+       }
+
+       /* server IP address (mountd/NFS) */
+       if (xdr_inaddr_decode(&recv_head, serv_addr)) {
+               RPC_PRINTF(("bp_getfile: bad server addr\n"));
+               return -1;
+       }
+
+       /* server pathname */
+       path_len = MAXPATHLEN - 1;
+       if (xdr_string_decode(&recv_head, pathname, &path_len)) {
+               RPC_PRINTF(("bp_getfile: bad server path\n"));
+               return -1;
+       }
+
+       /* success */
+       return 0;
+}
+
+
+/*
+ * eXternal Data Representation routines.
+ * (but with non-standard args...)
+ */
+
+
+int
+xdr_string_encode(char **pkt, char *str, int len)
+{
+       u_int32_t *lenp;
+       char *datap;
+       int padlen = (len + 3) & ~3;    /* padded length */
+
+       /* The data will be int aligned. */
+       lenp = (u_int32_t *)*pkt;
+       *pkt += sizeof(*lenp);
+       *lenp = htonl(len);
+
+       datap = *pkt;
+       *pkt += padlen;
+       (void)memcpy(datap, str, len);
+
+       return 0;
+}
+
+/* len_p: bufsize - 1 */
+int
+xdr_string_decode(char **pkt, char *str, int *len_p)
+{
+       u_int32_t *lenp;
+       char *datap;
+       int slen;       /* string length */
+       int plen;       /* padded length */
+
+       /* The data will be int aligned. */
+       lenp = (u_int32_t *)*pkt;
+       *pkt += sizeof(*lenp);
+       slen = ntohl(*lenp);
+       plen = (slen + 3) & ~3;
+
+       if (slen > *len_p)
+               slen = *len_p;
+       datap = *pkt;
+       *pkt += plen;
+       (void)memcpy(str, datap, slen);
+
+       str[slen] = '\0';
+       *len_p = slen;
+
+       return 0;
+}
+
+
+/* ia: network order */
+int
+xdr_inaddr_encode(char **pkt, struct in_addr ia)
+{
+       struct xdr_inaddr *xi;
+       u_char *cp;
+       int32_t *ip;
+       union {
+               n_long l;       /* network order */
+               u_char c[4];
+       } uia;
+
+       /* The data will be int aligned. */
+       xi = (struct xdr_inaddr *)*pkt;
+       *pkt += sizeof(*xi);
+       xi->atype = htonl(1);
+       uia.l = ia.s_addr;
+       cp = uia.c;
+       ip = xi->addr;
+       /*
+        * Note: the htonl() calls below DO NOT
+        * imply that uia.l is in host order.
+        * In fact this needs it in net order.
+        */
+       *ip++ = htonl((unsigned int)*cp++);
+       *ip++ = htonl((unsigned int)*cp++);
+       *ip++ = htonl((unsigned int)*cp++);
+       *ip++ = htonl((unsigned int)*cp++);
+
+       return 0;
+}
+
+/* ia: network order */
+int
+xdr_inaddr_decode(char **pkt, struct in_addr *ia)
+{
+       struct xdr_inaddr *xi;
+       u_char *cp;
+       int32_t *ip;
+       union {
+               n_long l;       /* network order */
+               u_char c[4];
+       } uia;
+
+       /* The data will be int aligned. */
+       xi = (struct xdr_inaddr *)*pkt;
+       *pkt += sizeof(*xi);
+       if (xi->atype != htonl(1)) {
+               RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n",
+                   ntohl(xi->atype)));
+               return -1;
+       }
+
+       cp = uia.c;
+       ip = xi->addr;
+       /*
+        * Note: the ntohl() calls below DO NOT
+        * imply that uia.l is in host order.
+        * In fact this needs it in net order.
+        */
+       *cp++ = ntohl(*ip++);
+       *cp++ = ntohl(*ip++);
+       *cp++ = ntohl(*ip++);
+       *cp++ = ntohl(*ip++);
+       ia->s_addr = uia.l;
+
+       return 0;
+}
diff --git a/sys/lib/libsa/bootparam.h b/sys/lib/libsa/bootparam.h
new file mode 100644 (file)
index 0000000..b60a2c7
--- /dev/null
@@ -0,0 +1,4 @@
+/*     $NetBSD: bootparam.h,v 1.4 2007/11/24 13:20:54 isaki Exp $      */
+
+int bp_whoami(int);
+int bp_getfile(int, char *, struct in_addr *, char *);
diff --git a/sys/lib/libsa/byteorder.c b/sys/lib/libsa/byteorder.c
new file mode 100644 (file)
index 0000000..204070d
--- /dev/null
@@ -0,0 +1,209 @@
+/*     $NetBSD: byteorder.c,v 1.3 2007/11/24 13:20:54 isaki Exp $      */
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed for the NetBSD Project by
+ *     Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "byteorder.h"
+
+typedef union {
+       uint16_t val;
+       uint8_t bytes[2];
+} un16;
+
+typedef union {
+       uint32_t val;
+       uint8_t bytes[4];
+} un32;
+
+typedef union {
+       uint64_t val;
+       uint32_t words[2];
+} un64;
+
+/* 16-bit */
+
+uint16_t
+sa_htobe16(uint16_t val)
+{
+       un16 un;
+
+       un.bytes[1] = val & 0xff;
+       un.bytes[0] = (val >> 8) & 0xff;
+
+       return un.val;
+}
+
+uint16_t
+sa_htole16(uint16_t val)
+{
+       un16 un;
+
+       un.bytes[0] = val & 0xff;
+       un.bytes[1] = (val >> 8) & 0xff;
+
+       return un.val;
+}
+
+uint16_t
+sa_be16toh(uint16_t val)
+{
+       un16 un;
+
+       un.val = val;
+
+       return ((un.bytes[0] << 8) |
+                un.bytes[1]);
+}
+
+uint16_t
+sa_le16toh(uint16_t val)
+{
+       un16 un;
+
+       un.val = val;
+
+       return ((un.bytes[1] << 8) |
+                un.bytes[0]);
+}
+
+/* 32-bit */
+
+uint32_t
+sa_htobe32(uint32_t val)
+{
+       un32 un;
+
+       un.bytes[3] = val & 0xff;
+       un.bytes[2] = (val >> 8) & 0xff;
+       un.bytes[1] = (val >> 16) & 0xff;
+       un.bytes[0] = (val >> 24) & 0xff;
+
+       return un.val;
+}
+
+uint32_t
+sa_htole32(uint32_t val)
+{
+       un32 un;
+
+       un.bytes[0] = val & 0xff;
+       un.bytes[1] = (val >> 8) & 0xff;
+       un.bytes[2] = (val >> 16) & 0xff;
+       un.bytes[3] = (val >> 24) & 0xff;
+
+       return un.val;
+}
+
+uint32_t
+sa_be32toh(uint32_t val)
+{
+       un32 un;
+
+       un.val = val;
+
+       return ((un.bytes[0] << 24) |
+               (un.bytes[1] << 16) |
+               (un.bytes[2] << 8) |
+                un.bytes[3]);
+}
+
+uint32_t
+sa_le32toh(uint32_t val)
+{
+       un32 un;
+
+       un.val = val;
+
+       return ((un.bytes[3] << 24) |
+               (un.bytes[2] << 16) |
+               (un.bytes[1] << 8) |
+                un.bytes[0]);
+}
+
+/* 64-bit */
+
+uint64_t
+sa_htobe64(uint64_t val)
+{
+       un64 un;
+
+       un.words[BE64_HI] = sa_htobe32(val >> 32);
+       un.words[BE64_LO] = sa_htobe32(val & 0xffffffffU);
+
+       return un.val;
+}
+
+uint64_t
+sa_htole64(uint64_t val)
+{
+       un64 un;
+
+       un.words[LE64_HI] = sa_htole32(val >> 32);
+       un.words[LE64_LO] = sa_htole32(val & 0xffffffffU);
+
+       return un.val;
+}
+
+uint64_t
+sa_be64toh(uint64_t val)
+{
+       un64 un;
+       uint64_t rv;
+
+       un.val = val;
+       un.words[BE64_HI] = sa_be32toh(un.words[BE64_HI]);
+       un.words[BE64_LO] = sa_be32toh(un.words[BE64_LO]);
+
+       rv = (((uint64_t)un.words[BE64_HI]) << 32) |
+            un.words[BE64_LO];
+
+       return rv;
+}
+
+uint64_t
+sa_le64toh(uint64_t val)
+{
+       un64 un;
+       uint64_t rv;
+
+       un.val = val;
+       un.words[LE64_HI] = sa_le32toh(un.words[LE64_HI]);
+       un.words[LE64_LO] = sa_le32toh(un.words[LE64_LO]);
+
+       rv = (((uint64_t)un.words[LE64_HI]) << 32) |
+            un.words[LE64_LO];
+
+       return rv;
+}
diff --git a/sys/lib/libsa/byteorder.h b/sys/lib/libsa/byteorder.h
new file mode 100644 (file)
index 0000000..ce040b8
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: byteorder.h,v 1.3 2001/10/31 20:22:22 thorpej Exp $    */
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed for the NetBSD Project by
+ *     Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LIBSA_BYTEORDER_H_
+#define        _LIBSA_BYTEORDER_H_
+
+#ifdef _STANDALONE
+#include <lib/libsa/stand.h>
+#else
+#include <inttypes.h>
+#endif
+
+uint16_t       sa_htobe16(uint16_t);
+uint16_t       sa_htole16(uint16_t);
+uint16_t       sa_be16toh(uint16_t);
+uint16_t       sa_le16toh(uint16_t);
+
+uint32_t       sa_htobe32(uint32_t);
+uint32_t       sa_htole32(uint32_t);
+uint32_t       sa_be32toh(uint32_t);
+uint32_t       sa_le32toh(uint32_t);
+
+uint64_t       sa_htobe64(uint64_t);
+uint64_t       sa_htole64(uint64_t);
+uint64_t       sa_be64toh(uint64_t);
+uint64_t       sa_le64toh(uint64_t);
+
+/* Order of the words in a big-endian 64-bit word. */
+#define        BE64_HI 0
+#define        BE64_LO 1
+
+/* Order of the words in a little-endian 64-bit word. */
+#define        LE64_HI 1
+#define        LE64_LO 0
+
+#endif /* _LIBSA_BYTEORDER_H_ */
diff --git a/sys/lib/libsa/cd9660.c b/sys/lib/libsa/cd9660.c
new file mode 100644 (file)
index 0000000..fa14180
--- /dev/null
@@ -0,0 +1,407 @@
+/*     $NetBSD: cd9660.c,v 1.28 2011/12/25 06:09:08 tsutsui Exp $      */
+
+/*
+ * Copyright (C) 1996 Wolfgang Solfrank.
+ * Copyright (C) 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Stand-alone ISO9660 file reading package.
+ *
+ * Note: This doesn't support Rock Ridge extensions, extended attributes,
+ * blocksizes other than 2048 bytes, multi-extent files, etc.
+ */
+#include <sys/param.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+#include <fs/cd9660/iso.h>
+
+#include "stand.h"
+#include "cd9660.h"
+
+/*
+ * XXX Does not currently implement:
+ * XXX
+ * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?)
+ * XXX LIBSA_FS_SINGLECOMPONENT
+ */
+
+struct file {
+       off_t off;                      /* Current offset within file */
+       daddr_t bno;                    /* Starting block number  */
+       off_t size;                     /* Size of file */
+};
+
+struct ptable_ent {
+       char namlen     [ISODCL( 1, 1)];        /* 711 */
+       char extlen     [ISODCL( 2, 2)];        /* 711 */
+       char block      [ISODCL( 3, 6)];        /* 732 */
+       char parent     [ISODCL( 7, 8)];        /* 722 */
+       char name       [1];
+};
+#define        PTFIXSZ         8
+#define        PTSIZE(pp)      roundup(PTFIXSZ + isonum_711((pp)->namlen), 2)
+
+#define        cdb2devb(bno)   ((bno) * ISO_DEFAULT_BLOCK_SIZE / DEV_BSIZE)
+
+static int     pnmatch(const char *, struct ptable_ent *);
+static int     dirmatch(const char *, struct iso_directory_record *);
+
+static int
+pnmatch(const char *path, struct ptable_ent *pp)
+{
+       char *cp;
+       int i;
+
+       cp = pp->name;
+       for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) {
+               if (toupper(*path) == *cp)
+                       continue;
+               return 0;
+       }
+       if (*path != '/')
+               return 0;
+       return 1;
+}
+
+static int
+dirmatch(const char *path, struct iso_directory_record *dp)
+{
+       char *cp;
+       int i;
+
+       /* This needs to be a regular file */
+       if (dp->flags[0] & 6)
+               return 0;
+
+       cp = dp->name;
+       for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) {
+               if (!*path)
+                       break;
+               if (toupper(*path) == *cp)
+                       continue;
+               return 0;
+       }
+       if (*path)
+               return 0;
+       /*
+        * Allow stripping of trailing dots and the version number.
+        * Note that this will find the first instead of the last version
+        * of a file.
+        */
+       if (i >= 0 && (*cp == ';' || *cp == '.')) {
+               /* This is to prevent matching of numeric extensions */
+               if (*cp == '.' && cp[1] != ';')
+                       return 0;
+               while (--i >= 0)
+                       if (*++cp != ';' && (*cp < '0' || *cp > '9'))
+                               return 0;
+       }
+       return 1;
+}
+
+__compactcall int
+cd9660_open(const char *path, struct open_file *f)
+{
+       struct file *fp = 0;
+       void *buf;
+       struct iso_primary_descriptor *vd;
+       size_t buf_size, nread, psize, dsize;
+       daddr_t bno;
+       int parent, ent;
+       struct ptable_ent *pp;
+       struct iso_directory_record *dp = 0;
+       int rc;
+
+       /* First find the volume descriptor */
+       buf_size = ISO_DEFAULT_BLOCK_SIZE;
+       buf = alloc(buf_size);
+       vd = buf;
+       for (bno = 16;; bno++) {
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
+                                          ISO_DEFAULT_BLOCK_SIZE, buf, &nread);
+               if (rc)
+                       goto out;
+               if (nread != ISO_DEFAULT_BLOCK_SIZE) {
+                       rc = EIO;
+                       goto out;
+               }
+               rc = EINVAL;
+               if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
+                       goto out;
+               if (isonum_711(vd->type) == ISO_VD_END)
+                       goto out;
+               if (isonum_711(vd->type) == ISO_VD_PRIMARY)
+                       break;
+       }
+       if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
+               goto out;
+
+       /* Now get the path table and lookup the directory of the file */
+       bno = isonum_732(vd->type_m_path_table);
+       psize = isonum_733(vd->path_table_size);
+
+       if (psize > ISO_DEFAULT_BLOCK_SIZE) {
+               dealloc(buf, ISO_DEFAULT_BLOCK_SIZE);
+               buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE));
+       }
+
+#if !defined(LIBSA_NO_TWIDDLE)
+       twiddle();
+#endif
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
+                                  buf_size, buf, &nread);
+       if (rc)
+               goto out;
+       if (nread != buf_size) {
+               rc = EIO;
+               goto out;
+       }
+
+       parent = 1;
+       pp = (struct ptable_ent *)buf;
+       ent = 1;
+       bno = isonum_732(pp->block) + isonum_711(pp->extlen);
+
+       rc = ENOENT;
+
+       while (*path) {
+               /*
+                * Remove extra separators
+                */
+               while (*path == '/')
+                       path++;
+
+               if ((char *)pp >= (char *)buf + psize)
+                       break;
+               if (isonum_722(pp->parent) != parent)
+                       break;
+               if (!pnmatch(path, pp)) {
+                       pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
+                       ent++;
+                       continue;
+               }
+               path += isonum_711(pp->namlen) + 1;
+               parent = ent;
+               bno = isonum_732(pp->block) + isonum_711(pp->extlen);
+               while ((char *)pp < (char *)buf + psize) {
+                       if (isonum_722(pp->parent) == parent)
+                               break;
+                       pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
+                       ent++;
+               }
+       }
+
+       /*
+        * Now bno has the start of the directory that supposedly
+        * contains the file
+        */
+       bno--;
+       dsize = 1;              /* Something stupid, but > 0 XXX */
+       for (psize = 0; psize < dsize;) {
+               if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) {
+                       bno++;
+#if !defined(LIBSA_NO_TWIDDLE)
+                       twiddle();
+#endif
+                       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                                                  cdb2devb(bno),
+                                                  ISO_DEFAULT_BLOCK_SIZE,
+                                                  buf, &nread);
+                       if (rc)
+                               goto out;
+                       if (nread != ISO_DEFAULT_BLOCK_SIZE) {
+                               rc = EIO;
+                               goto out;
+                       }
+                       dp = (struct iso_directory_record *)buf;
+               }
+               if (!isonum_711(dp->length)) {
+                       if ((void *)dp == buf)
+                               psize += ISO_DEFAULT_BLOCK_SIZE;
+                       else
+                               psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE);
+                       continue;
+               }
+               if (dsize == 1)
+                       dsize = isonum_733(dp->size);
+               if (dirmatch(path, dp))
+                       break;
+               psize += isonum_711(dp->length);
+               dp = (struct iso_directory_record *)
+                       ((char *)dp + isonum_711(dp->length));
+       }
+
+       if (psize >= dsize) {
+               rc = ENOENT;
+               goto out;
+       }
+
+       /* allocate file system specific data structure */
+       fp = alloc(sizeof(struct file));
+       memset(fp, 0, sizeof(struct file));
+       f->f_fsdata = (void *)fp;
+
+       fp->off = 0;
+       fp->bno = isonum_733(dp->extent);
+       fp->size = isonum_733(dp->size);
+       dealloc(buf, buf_size);
+       fsmod = "cd9660";
+
+       return 0;
+
+out:
+       if (fp)
+               dealloc(fp, sizeof(struct file));
+       dealloc(buf, buf_size);
+
+       return rc;
+}
+
+#if !defined(LIBSA_NO_FS_CLOSE)
+__compactcall int
+cd9660_close(struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       f->f_fsdata = 0;
+       dealloc(fp, sizeof *fp);
+
+       return 0;
+}
+#endif /* !defined(LIBSA_NO_FS_CLOSE) */
+
+__compactcall int
+cd9660_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       int rc = 0;
+       daddr_t bno;
+       char buf[ISO_DEFAULT_BLOCK_SIZE];
+       char *dp;
+       size_t nread, off;
+
+       while (size) {
+               if (fp->off < 0 || fp->off >= fp->size)
+                       break;
+               bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno;
+               if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1)
+                   || size < ISO_DEFAULT_BLOCK_SIZE)
+                       dp = buf;
+               else
+                       dp = start;
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
+                                           ISO_DEFAULT_BLOCK_SIZE, dp, &nread);
+               if (rc)
+                       return rc;
+               if (nread != ISO_DEFAULT_BLOCK_SIZE)
+                       return EIO;
+               if (dp == buf) {
+                       off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1);
+                       if (nread > off + size)
+                               nread = off + size;
+                       nread -= off;
+                       memcpy(start, buf + off, nread);
+                       start = (char *)start + nread;
+                       fp->off += nread;
+                       size -= nread;
+               } else {
+                       start = (char *)start + ISO_DEFAULT_BLOCK_SIZE;
+                       fp->off += ISO_DEFAULT_BLOCK_SIZE;
+                       size -= ISO_DEFAULT_BLOCK_SIZE;
+               }
+       }
+       if(fp->off > fp->size)
+               size += fp->off - fp->size;
+       if (resid)
+               *resid = size;
+       return rc;
+}
+
+#if !defined(LIBSA_NO_FS_WRITE)
+__compactcall int
+cd9660_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !defined(LIBSA_NO_FS_WRITE) */
+
+#if !defined(LIBSA_NO_FS_SEEK)
+__compactcall off_t
+cd9660_seek(struct open_file *f, off_t offset, int where)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               fp->off = offset;
+               break;
+       case SEEK_CUR:
+               fp->off += offset;
+               break;
+       case SEEK_END:
+               fp->off = fp->size - offset;
+               break;
+       default:
+               return -1;
+       }
+       return fp->off;
+}
+#endif /* !defined(LIBSA_NO_FS_SEEK) */
+
+__compactcall int
+cd9660_stat(struct open_file *f, struct stat *sb)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       /* only importatn stuff */
+       sb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
+       sb->st_uid = sb->st_gid = 0;
+       sb->st_size = fp->size;
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+cd9660_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by cd9660\n");
+       return;
+}
+#endif
diff --git a/sys/lib/libsa/cd9660.h b/sys/lib/libsa/cd9660.h
new file mode 100644 (file)
index 0000000..74f740f
--- /dev/null
@@ -0,0 +1,34 @@
+/*     $NetBSD: cd9660.h,v 1.3 2005/12/11 12:24:46 christos Exp $      */
+
+/*
+ * Copyright (C) 1996 Wolfgang Solfrank.
+ * Copyright (C) 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FS_DEF(cd9660);
diff --git a/sys/lib/libsa/checkpasswd.c b/sys/lib/libsa/checkpasswd.c
new file mode 100644 (file)
index 0000000..df7c28a
--- /dev/null
@@ -0,0 +1,131 @@
+/*     $NetBSD: checkpasswd.c,v 1.9 2011/01/06 02:45:13 jakllsch Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)gets.c      8.1 (Berkeley) 6/11/93
+ */
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+
+char *
+getpass(const char *prompt)
+{
+       int c;
+       char *lp;
+       static char buf[128]; /* == _PASSWORD_LEN */
+
+       printf("%s", prompt);
+
+       for (lp = buf;;) {
+               switch (c = getchar() & 0177) {
+               case '\n':
+               case '\r':
+                       *lp = '\0';
+                       putchar('\n');
+                       return buf;
+               case '\b':
+               case '\177':
+                       if (lp > buf) {
+                               lp--;
+                               putchar('\b');
+                               putchar(' ');
+                               putchar('\b');
+                       }
+                       break;
+#if HASH_ERASE
+               case '#':
+                       if (lp > buf)
+                               --lp;
+                       break;
+#endif
+               case 'r'&037: {
+                       char *p;
+
+                       putchar('\n');
+                       for (p = buf; p < lp; ++p)
+                               putchar('*');
+                       break;
+               }
+#if AT_ERASE
+               case '@':
+#endif
+               case 'u'&037:
+               case 'w'&037:
+                       lp = buf;
+                       putchar('\n');
+                       break;
+               default:
+                       *lp++ = c;
+                       putchar('*');
+                       break;
+               }
+       }
+       /*NOTREACHED*/
+}
+
+#include <sys/md5.h>
+
+char bootpasswd[16] = {'\0'}; /* into data segment! */
+
+int
+checkpasswd(void)
+{
+
+       return check_password(bootpasswd);
+}
+
+int
+check_password(const char *password)
+{
+       int i;
+       char *passwd;
+       MD5_CTX md5ctx;
+       char pwdigest[16];
+
+       for (i = 0; i < 16; i++)
+               if (password[i])
+                       break;
+       if (i == 16)
+               return 1; /* no password set */
+
+       for (i = 0; i < 3; i++) {
+               passwd = getpass("Password: ");
+               MD5Init(&md5ctx);
+               MD5Update(&md5ctx, passwd, strlen(passwd));
+               MD5Final(pwdigest, &md5ctx);
+               if (memcmp(pwdigest, password, 16) == 0)
+                       return 1;
+       }
+
+       /* failed */
+       return 0;
+}
diff --git a/sys/lib/libsa/close.c b/sys/lib/libsa/close.c
new file mode 100644 (file)
index 0000000..45d0a57
--- /dev/null
@@ -0,0 +1,103 @@
+/*     $NetBSD: close.c,v 1.14 2007/12/02 04:59:25 tsutsui Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)close.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+int
+#ifndef __INTERNAL_LIBSA_CREAD
+close(int fd)
+#else
+oclose(int fd)
+#endif
+{
+       struct open_file *f = &files[fd];
+       int err1 = 0, err2 = 0;
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       if (!(f->f_flags & F_RAW))
+#endif
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+               if (f->f_ops != NULL)
+#endif
+                       err1 = FS_CLOSE(f->f_ops)(f);
+       if (!(f->f_flags & F_NODEV))
+#if !defined(LIBSA_SINGLE_DEVICE)
+               if (f->f_dev != NULL)
+#endif
+                       err2 = DEV_CLOSE(f->f_dev)(f);
+       f->f_flags = 0;
+       if (err1) {
+               errno = err1;
+               return -1;
+       }
+       if (err2) {
+               errno = err2;
+               return -1;
+       }
+       return 0;
+}
diff --git a/sys/lib/libsa/closeall.c b/sys/lib/libsa/closeall.c
new file mode 100644 (file)
index 0000000..a8f8121
--- /dev/null
@@ -0,0 +1,73 @@
+/*     $NetBSD: closeall.c,v 1.5 2007/11/24 13:20:54 isaki Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)close.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+void
+closeall(void)
+{
+       int i;
+
+       for (i = 0; i < SOPEN_MAX; i++)
+               if (files[i].f_flags != 0)
+                       (void)close(i);
+}
diff --git a/sys/lib/libsa/cread.c b/sys/lib/libsa/cread.c
new file mode 100644 (file)
index 0000000..808690c
--- /dev/null
@@ -0,0 +1,493 @@
+/*     $NetBSD: cread.c,v 1.23 2009/03/25 18:41:06 tls Exp $   */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Support for compressed bootfiles  (only read)
+ *
+ * - replaces open(), close(), read(), lseek().
+ * - original libsa open(), close(), read(), lseek() are called
+ *   as oopen(), oclose(), oread() resp. olseek().
+ * - compression parts stripped from zlib:gzio.c
+ */
+
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "stand.h"
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#include <lib/libz/libz.h>
+#else
+#include <string.h>
+#include <zlib.h>
+#endif
+
+#define EOF (-1) /* needed by compression code */
+
+#ifdef SAVE_MEMORY
+#define Z_BUFSIZE 1024
+#else
+#define Z_BUFSIZE 4096
+#endif
+
+static const int gz_magic[2] = {0x1f, 0x8b};   /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG     0x01    /* bit 0 set: file probably ascii text */
+#define HEAD_CRC       0x02    /* bit 1 set: header CRC present */
+#define EXTRA_FIELD    0x04    /* bit 2 set: extra field present */
+#define ORIG_NAME      0x08    /* bit 3 set: original file name present */
+#define COMMENT                0x10    /* bit 4 set: file comment present */
+#define RESERVED       0xE0    /* bits 5..7: reserved */
+
+static struct sd {
+       z_stream        stream;
+       int             z_err;  /* error code for last stream operation */
+       int             z_eof;  /* set if end of input file */
+       int             fd;
+       unsigned char   *inbuf; /* input buffer */
+       unsigned long   crc;    /* crc32 of uncompressed data */
+       int             compressed;     /* 1 if input file is a .gz file */
+} *ss[SOPEN_MAX];
+
+static int             get_byte(struct sd *);
+static unsigned long   getLong(struct sd *);
+static void            check_header(struct sd *);
+
+/* XXX - find suitable header file for these: */
+void   *zcalloc(void *, unsigned int, unsigned int);
+void   zcfree(void *, void *);
+void   zmemcpy(unsigned char *, unsigned char *, unsigned int);
+
+/*
+ * The libkern version of this function uses an 8K set of tables.
+ * This is the double-loop version of LE CRC32 from if_ethersubr,
+ * lightly modified -- it is 200 bytes smaller than the version using
+ * a 4-bit table and at least 8K smaller than the libkern version.
+ */
+#ifndef ETHER_CRC_POLY_LE
+#define ETHER_CRC_POLY_LE      0xedb88320
+#endif
+uint32_t
+crc32(uint32_t crc, const uint8_t *const buf, size_t len)
+{
+       uint32_t c, carry;
+       size_t i, j;
+
+       crc = 0xffffffffU ^ crc;
+       for (i = 0; i < len; i++) {
+           c = buf[i];
+           for (j = 0; j < 8; j++) {
+               carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+               crc >>= 1;
+               c >>= 1;
+               if (carry) {
+                       crc = (crc ^ ETHER_CRC_POLY_LE);
+               }
+           }
+       }
+       return (crc ^ 0xffffffffU);
+}
+
+/*
+ * compression utilities
+ */
+
+void *
+zcalloc(void *opaque, unsigned int items, unsigned int size)
+{
+
+       return alloc(items * size);
+}
+
+void
+zcfree(void *opaque, void *ptr)
+{
+
+       dealloc(ptr, 0); /* XXX works only with modified allocator */
+}
+
+void
+zmemcpy(unsigned char *dest, unsigned char *source, unsigned int len)
+{
+
+       memcpy(dest, source, len);
+}
+
+static int
+get_byte(struct sd *s)
+{
+       if (s->z_eof)
+               return EOF;
+
+       if (s->stream.avail_in == 0) {
+               int got;
+
+               errno = 0;
+               got = oread(s->fd, s->inbuf, Z_BUFSIZE);
+               if (got <= 0) {
+                       s->z_eof = 1;
+                       if (errno)
+                               s->z_err = Z_ERRNO;
+                       return EOF;
+               }
+               s->stream.avail_in = got;
+               s->stream.next_in = s->inbuf;
+       }
+       s->stream.avail_in--;
+       return *(s->stream.next_in)++;
+}
+
+static unsigned long
+getLong(struct sd *s)
+{
+       unsigned long x;
+       int c;
+
+       x  =  (unsigned long)get_byte(s);
+       x += ((unsigned long)get_byte(s)) << 8;
+       x += ((unsigned long)get_byte(s)) << 16;
+       c = get_byte(s);
+       if (c == EOF)
+               s->z_err = Z_DATA_ERROR;
+       x += ((unsigned long)c) << 24;
+       return x;
+}
+
+static void
+check_header(struct sd *s)
+{
+       int method; /* method byte */
+       int flags;  /* flags byte */
+       unsigned int len;
+       int c;
+
+       /* Check the gzip magic header */
+       for (len = 0; len < 2; len++) {
+               c = get_byte(s);
+               if (c == gz_magic[len])
+                       continue;
+               if ((c == EOF) && (len == 0))  {
+                       /*
+                        * We must not change s->compressed if we are at EOF;
+                        * we may have come to the end of a gzipped file and be
+                        * check to see if another gzipped file is concatenated
+                        * to this one. If one isn't, we still need to be able
+                        * to lseek on this file as a compressed file.
+                        */
+                       return;
+               }
+               s->compressed = 0;
+               if (c != EOF) {
+                       s->stream.avail_in++;
+                       s->stream.next_in--;
+               }
+               s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
+               return;
+       }
+       s->compressed = 1;
+       method = get_byte(s);
+       flags = get_byte(s);
+       if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+               s->z_err = Z_DATA_ERROR;
+               return;
+       }
+
+       /* Discard time, xflags and OS code: */
+       for (len = 0; len < 6; len++)
+               (void)get_byte(s);
+
+       if ((flags & EXTRA_FIELD) != 0) {
+               /* skip the extra field */
+               len  =  (unsigned int)get_byte(s);
+               len += ((unsigned int)get_byte(s)) << 8;
+               /* len is garbage if EOF but the loop below will quit anyway */
+               while (len-- != 0 && get_byte(s) != EOF)
+                       /*void*/;
+       }
+       if ((flags & ORIG_NAME) != 0) {
+               /* skip the original file name */
+               while ((c = get_byte(s)) != 0 && c != EOF)
+                       /*void*/;
+       }
+       if ((flags & COMMENT) != 0) {
+               /* skip the .gz file comment */
+               while ((c = get_byte(s)) != 0 && c != EOF)
+                       /*void*/;
+       }
+       if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
+               for (len = 0; len < 2; len++)
+                       (void)get_byte(s);
+       }
+       s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+/*
+ * new open(), close(), read(), lseek()
+ */
+
+int
+open(const char *fname, int mode)
+{
+       int fd;
+       struct sd *s = 0;
+
+       if (((fd = oopen(fname, mode)) == -1) || (mode != 0))
+               /* compression only for read */
+               return fd;
+
+       ss[fd] = s = alloc(sizeof(struct sd));
+       if (s == 0)
+               goto errout;
+       (void)memset(s, 0, sizeof(struct sd));
+
+       if (inflateInit2(&(s->stream), -15) != Z_OK)
+               goto errout;
+
+       s->stream.next_in = s->inbuf = (unsigned char *)alloc(Z_BUFSIZE);
+       if (s->inbuf == 0) {
+               inflateEnd(&(s->stream));
+               goto errout;
+       }
+
+       s->fd = fd;
+       check_header(s); /* skip the .gz header */
+       return fd;
+
+errout:
+       if (s != 0)
+               dealloc(s, sizeof(struct sd));
+       oclose(fd);
+       return -1;
+}
+
+int
+close(int fd)
+{
+       struct open_file *f;
+       struct sd *s;
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+       f = &files[fd];
+
+       if ((f->f_flags & F_READ) == 0)
+               return oclose(fd);
+
+       s = ss[fd];
+
+       inflateEnd(&(s->stream));
+
+       dealloc(s->inbuf, Z_BUFSIZE);
+       dealloc(s, sizeof(struct sd));
+
+       return oclose(fd);
+}
+
+ssize_t
+read(int fd, void *buf, size_t len)
+{
+       struct sd *s;
+       unsigned char *start = buf; /* starting point for crc computation */
+
+       s = ss[fd];
+
+       if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
+               return -1;
+       if (s->z_err == Z_STREAM_END)
+               return 0;  /* EOF */
+
+       s->stream.next_out = buf;
+       s->stream.avail_out = len;
+
+       while (s->stream.avail_out != 0) {
+
+               if (s->compressed == 0) {
+                       /* Copy first the lookahead bytes: */
+                       unsigned int n = s->stream.avail_in;
+                       if (n > s->stream.avail_out)
+                               n = s->stream.avail_out;
+                       if (n > 0) {
+                               zmemcpy(s->stream.next_out,
+                                       s->stream.next_in, n);
+                               s->stream.next_out  += n;
+                               s->stream.next_in   += n;
+                               s->stream.avail_out -= n;
+                               s->stream.avail_in  -= n;
+                       }
+                       if (s->stream.avail_out > 0) {
+                               int got;
+                               got = oread(s->fd, s->stream.next_out,
+                                           s->stream.avail_out);
+                               if (got == -1)
+                                       return got;
+                               s->stream.avail_out -= got;
+                       }
+                       return (int)(len - s->stream.avail_out);
+               }
+
+               if (s->stream.avail_in == 0 && !s->z_eof) {
+                       int got;
+                       errno = 0;
+                       got = oread(fd, s->inbuf, Z_BUFSIZE);
+                       if (got <= 0) {
+                               s->z_eof = 1;
+                               if (errno) {
+                                       s->z_err = Z_ERRNO;
+                                       break;
+                               }
+                       }
+                       s->stream.avail_in = got;
+                       s->stream.next_in = s->inbuf;
+               }
+
+               s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+
+               if (s->z_err == Z_STREAM_END) {
+                       /* Check CRC and original size */
+                       s->crc = crc32(s->crc, start, (unsigned int)
+                                       (s->stream.next_out - start));
+                       start = s->stream.next_out;
+
+                       if (getLong(s) != s->crc ||
+                           getLong(s) != s->stream.total_out) {
+
+                               s->z_err = Z_DATA_ERROR;
+                       } else {
+                               /* Check for concatenated .gz files: */
+                               check_header(s);
+                               if (s->z_err == Z_OK) {
+                                       inflateReset(&(s->stream));
+                                       s->crc = crc32(0L, Z_NULL, 0);
+                               }
+                       }
+               }
+               if (s->z_err != Z_OK || s->z_eof)
+                       break;
+       }
+
+       s->crc = crc32(s->crc, start,
+                      (unsigned int)(s->stream.next_out - start));
+
+       return (int)(len - s->stream.avail_out);
+}
+
+off_t
+lseek(int fd, off_t offset, int where)
+{
+       struct open_file *f;
+       struct sd *s;
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+       f = &files[fd];
+
+       if ((f->f_flags & F_READ) == 0)
+               return olseek(fd, offset, where);
+
+       s = ss[fd];
+
+       if(s->compressed == 0) {
+               off_t res = olseek(fd, offset, where);
+               if (res != (off_t)-1) {
+                       /* make sure the lookahead buffer is invalid */
+                       s->stream.avail_in = 0;
+               }
+               return res;
+       }
+
+       switch(where) {
+       case SEEK_CUR:
+               offset += s->stream.total_out;
+       case SEEK_SET:
+               /* if seek backwards, simply start from the beginning */
+               if (offset < s->stream.total_out) {
+                       off_t res;
+                       void *sav_inbuf;
+
+                       res = olseek(fd, 0, SEEK_SET);
+                       if(res == (off_t)-1)
+                               return res;
+                       /* ??? perhaps fallback to close / open */
+
+                       inflateEnd(&(s->stream));
+
+                       sav_inbuf = s->inbuf; /* don't allocate again */
+                       (void)memset(s, 0, sizeof(struct sd));
+                       /* this resets total_out to 0! */
+
+                       inflateInit2(&(s->stream), -15);
+                       s->stream.next_in = s->inbuf = sav_inbuf;
+
+                       s->fd = fd;
+                       check_header(s); /* skip the .gz header */
+               }
+
+               /* to seek forwards, throw away data */
+               if (offset > s->stream.total_out) {
+                       off_t toskip = offset - s->stream.total_out;
+
+                       while (toskip > 0) {
+#define DUMMYBUFSIZE 256
+                               char dummybuf[DUMMYBUFSIZE];
+                               off_t len = toskip;
+
+                               if (len > DUMMYBUFSIZE)
+                                       len = DUMMYBUFSIZE;
+                               if (read(fd, dummybuf, len) != len) {
+                                       errno = EOFFSET;
+                                       return (off_t)-1;
+                               }
+                               toskip -= len;
+                       }
+               }
+#ifdef DEBUG
+               if (offset != s->stream.total_out)
+                       panic("lseek compressed");
+#endif
+               return offset;
+       case SEEK_END:
+               errno = EOFFSET;
+               break;
+       default:
+               errno = EINVAL;
+               break;
+       }
+
+       return (off_t)-1;
+}
diff --git a/sys/lib/libsa/dev.c b/sys/lib/libsa/dev.c
new file mode 100644 (file)
index 0000000..793aeca
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: dev.c,v 1.8 2007/11/24 13:20:54 isaki Exp $    */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)dev.c       8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+
+#include "stand.h"
+
+int
+nodev(void)
+{
+
+       return ENXIO;
+}
+
+void
+nullsys(void)
+{
+}
+
+/* ARGSUSED */
+int
+noioctl(struct open_file *f, u_long cmd, void *data)
+{
+
+       return EINVAL;
+}
diff --git a/sys/lib/libsa/dev_net.c b/sys/lib/libsa/dev_net.c
new file mode 100644 (file)
index 0000000..a15c000
--- /dev/null
@@ -0,0 +1,284 @@
+/*     $NetBSD: dev_net.c,v 1.26 2011/07/17 20:54:52 joerg Exp $       */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Gordon W. Ross.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This module implements a "raw device" interface suitable for
+ * use by the stand-alone I/O library NFS code.  This interface
+ * does not support any "block" access, and exists only for the
+ * purpose of initializing the network interface, getting boot
+ * parameters, and performing the NFS mount.
+ *
+ * At open time, this does:
+ *
+ * find interface      - netif_open()
+ * RARP for IP address - rarp_getipaddress()
+ * RPC/bootparams      - callrpc(d, RPC_BOOTPARAMS, ...)
+ * RPC/mountd          - nfs_mount(sock, ip, path)
+ *
+ * the root file handle from mountd is saved in a global
+ * for use by the NFS open code (NFS/lookup).
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include <lib/libkern/libkern.h>
+
+#include "stand.h"
+#include "net.h"
+#include "netif.h"
+#include "nfs.h"
+#include "bootparam.h"
+#include "dev_net.h"
+#ifdef SUPPORT_BOOTP
+#include "bootp.h"
+#endif
+
+extern int nfs_root_node[];    /* XXX - get from nfs_mount() */
+
+static int netdev_sock = -1;
+static int netdev_opens;
+
+static int net_getparams(int);
+
+/*
+ * Called by devopen after it sets f->f_dev to our devsw entry.
+ * This opens the low-level device and sets f->f_devdata.
+ * This is declared with variable arguments...
+ */
+int
+net_open(struct open_file *f, ...)
+{
+       va_list ap;
+       char *devname;          /* Device part of file name (or NULL). */
+       int error = 0;
+
+       va_start(ap, f);
+       devname = va_arg(ap, char *);
+       va_end(ap);
+
+#ifdef NETIF_DEBUG
+       if (debug)
+               printf("%s\n", devname);
+#endif
+
+       /* On first open, do netif open, mount, etc. */
+       if (netdev_opens == 0) {
+               /* Find network interface. */
+               if (netdev_sock < 0) {
+                       netdev_sock = netif_open(devname);
+                       if (netdev_sock < 0) {
+                               printf("netif_open() failed\n");
+                               return ENXIO;
+                       }
+#ifdef NETIF_DEBUG
+                       if (debug)
+                               printf("netif_open() succeeded\n");
+#endif
+               }
+               if (rootip.s_addr == 0) {
+                       /* Get root IP address, and path, etc. */
+                       error = net_getparams(netdev_sock);
+                       if (error) {
+                               /* getparams makes its own noise */
+                               goto fail;
+                       }
+                       /* Get the NFS file handle (mountd). */
+                       error = nfs_mount(netdev_sock, rootip, rootpath);
+                       if (error) {
+                               printf("NFS mount error=%d\n", errno);
+                               rootip.s_addr = 0;
+                       fail:
+                               netif_close(netdev_sock);
+                               netdev_sock = -1;
+                               return error;
+                       }
+#ifdef NETIF_DEBUG
+                       if (debug)
+                               printf("NFS mount succeeded\n");
+#endif
+               }
+       }
+       netdev_opens++;
+       f->f_devdata = nfs_root_node;
+       return error;
+}
+
+int
+net_close(struct open_file *f)
+{
+
+#ifdef NETIF_DEBUG
+       if (debug)
+               printf("net_close: opens=%d\n", netdev_opens);
+#endif
+
+       /* On last close, do netif close, etc. */
+       f->f_devdata = NULL;
+       /* Extra close call? */
+       if (netdev_opens <= 0)
+               return 0;
+       netdev_opens--;
+       /* Not last close? */
+       if (netdev_opens > 0)
+               return 0;
+       rootip.s_addr = 0;
+       if (netdev_sock >= 0) {
+#ifdef NETIF_DEBUG
+               if (debug)
+                       printf("net_close: calling netif_close()\n");
+#endif
+               netif_close(netdev_sock);
+               netdev_sock = -1;
+       }
+       return 0;
+}
+
+int
+net_ioctl(struct open_file *f, u_long cmd, void *data)
+{
+
+       return EIO;
+}
+
+int
+net_strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf,
+       size_t *rsize)
+{
+
+       return EIO;
+}
+
+
+/*
+ * Get info for NFS boot: our IP address, our hostname,
+ * server IP address, and our root path on the server.
+ * There are two ways to do this:  The old, Sun way,
+ * and the more modern, BOOTP way. (RFC951, RFC1048)
+ *
+ * The default is to use the Sun bootparams RPC
+ * (because that is what the kernel will do).
+ * MD code can make try_bootp initialied data,
+ * which will override this common definition.
+ */
+#ifdef SUPPORT_BOOTP
+int try_bootp;
+#endif
+
+static int
+net_getparams(int sock)
+{
+       char buf[MAXHOSTNAMELEN];
+       n_long smask;
+
+#ifdef SUPPORT_BOOTP
+       /*
+        * Try to get boot info using BOOTP.  If we succeed, then
+        * the server IP address, gateway, and root path will all
+        * be initialized.  If any remain uninitialized, we will
+        * use RARP and RPC/bootparam (the Sun way) to get them.
+        */
+       if (try_bootp)
+               bootp(sock);
+       if (myip.s_addr != 0)
+               return 0;
+#ifdef NETIF_DEBUG
+       if (debug)
+               printf("BOOTP failed, trying RARP/RPC...\n");
+#endif
+#endif
+
+       /*
+        * Use RARP to get our IP address.  This also sets our
+        * netmask to the "natural" default for our address.
+        */
+       if (rarp_getipaddress(sock)) {
+               printf("RARP failed\n");
+               return EIO;
+       }
+#ifdef NETIF_DEBUG
+       if (debug)
+               printf("client addr: %s\n", inet_ntoa(myip));
+#endif
+
+       /* Get our hostname, server IP address, gateway. */
+       if (bp_whoami(sock)) {
+               printf("bootparam/whoami RPC failed\n");
+               return EIO;
+       }
+#ifdef NETIF_DEBUG
+       if (debug)
+               printf("client name: %s\n", hostname);
+#endif
+
+       /*
+        * Ignore the gateway from whoami (unreliable).
+        * Use the "gateway" parameter instead.
+        */
+       smask = 0;
+       gateip.s_addr = 0;
+       if (bp_getfile(sock, "gateway", &gateip, buf)) {
+               printf("nfs_open: gateway bootparam missing\n");
+       } else {
+               /* Got it!  Parse the netmask. */
+               smask = inet_addr(buf);
+       }
+       if (smask) {
+               netmask = smask;
+#ifdef NETIF_DEBUG
+               if (debug)
+                       printf("subnet mask: %s\n", intoa(netmask));
+#endif
+       }
+#ifdef NETIF_DEBUG
+       if (debug)
+               if (gateip.s_addr)
+                       printf("net gateway: %s\n", inet_ntoa(gateip));
+#endif
+
+       /* Get the root server and pathname. */
+       if (bp_getfile(sock, "root", &rootip, rootpath)) {
+               printf("bootparam/getfile RPC failed\n");
+               return EIO;
+       }
+
+#ifdef NETIF_DEBUG
+       if (debug) {
+               printf("server addr: %s\n", inet_ntoa(rootip));
+               printf("server path: %s\n", rootpath);
+       }
+#endif
+
+       return 0;
+}
diff --git a/sys/lib/libsa/dev_net.h b/sys/lib/libsa/dev_net.h
new file mode 100644 (file)
index 0000000..c4de3cc
--- /dev/null
@@ -0,0 +1,10 @@
+/*     $NetBSD: dev_net.h,v 1.6 2009/01/17 14:00:36 tsutsui Exp $      */
+
+int    net_open(struct open_file *, ...);
+int    net_close(struct open_file *);
+int    net_ioctl(struct open_file *, u_long, void *);
+int    net_strategy(void *, int , daddr_t , size_t, void *, size_t *);
+
+#ifdef SUPPORT_BOOTP
+extern int try_bootp;
+#endif
diff --git a/sys/lib/libsa/disklabel.c b/sys/lib/libsa/disklabel.c
new file mode 100644 (file)
index 0000000..f6aca5a
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: disklabel.c,v 1.10 2007/11/24 13:20:54 isaki Exp $     */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)disklabel.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+
+
+#if defined(LIBSA_NO_DISKLABEL_MSGS)
+#define nolabel (char *)1
+#define corruptedlabel (char *)1
+#else
+static char nolabel[] = "no disk label";
+static char corruptedlabel[] = "disk label corrupted";
+#endif
+
+char *
+getdisklabel(const char *buf, struct disklabel *lp)
+{
+       const struct disklabel *dlp, *elp;
+       char *msg = NULL;
+
+       elp = (const void *)(buf + DEV_BSIZE - sizeof(*dlp));
+       for (dlp = (const void *)buf; dlp <= elp;
+           dlp = (const void *)((const char *)dlp + sizeof(long))) {
+               if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+                       if (msg == NULL)
+                               msg = nolabel;
+               } else if (dlp->d_npartitions > MAXPARTITIONS ||
+                          dkcksum(dlp) != 0) {
+                       msg = corruptedlabel;
+               } else {
+                       (void)memcpy(lp, dlp, sizeof *lp);
+                       msg = NULL;
+                       break;
+               }
+       }
+       return msg;
+}
diff --git a/sys/lib/libsa/dkcksum.c b/sys/lib/libsa/dkcksum.c
new file mode 100644 (file)
index 0000000..3a96cc4
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD: dkcksum.c,v 1.5 2005/12/11 12:24:46 christos Exp $     */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)disklabel.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "stand.h"
+
+/*
+ * Compute checksum for disk label.
+ */
+int
+dkcksum(const struct disklabel *lp)
+{
+       const u_short *start, *end;
+       u_short sum = 0;
+
+       start = (const void *)lp;
+       end = (const void *)&lp->d_partitions[lp->d_npartitions];
+       while (start < end)
+               sum ^= *start++;
+       return sum;
+}
diff --git a/sys/lib/libsa/dosfs.c b/sys/lib/libsa/dosfs.c
new file mode 100644 (file)
index 0000000..82ddfbd
--- /dev/null
@@ -0,0 +1,797 @@
+/*     $NetBSD: dosfs.c,v 1.18 2011/12/25 06:09:08 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 1996, 1998 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Readonly filesystem for Microsoft FAT12/FAT16/FAT32 filesystems,
+ * also supports VFAT.
+ */
+
+/*
+ * XXX DOES NOT SUPPORT:
+ *
+ *     LIBSA_FS_SINGLECOMPONENT
+ */
+
+#include <sys/param.h>
+
+#include <fs/msdosfs/bpb.h>
+#include <fs/msdosfs/direntry.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#include <stddef.h>
+#endif
+
+#include "stand.h"
+#include "dosfs.h"
+
+#define SECSIZ  512            /* sector size */
+#define SSHIFT    9            /* SECSIZ shift */
+#define DEPSEC   16            /* directory entries per sector */
+#define DSHIFT    4            /* DEPSEC shift */
+#define LOCLUS    2            /* lowest cluster number */
+
+typedef union {
+       struct direntry de;     /* standard directory entry */
+       struct winentry xde;    /* extended directory entry */
+} DOS_DIR;
+
+typedef struct {
+       struct open_file *fd;   /* file descriptor */
+       u_char *buf;            /* buffer */
+       u_int   bufsec;         /* buffered sector */
+       u_int   links;          /* active links to structure */
+       u_int   spc;            /* sectors per cluster */
+       u_int   bsize;          /* cluster size in bytes */
+       u_int   bshift;         /* cluster conversion shift */
+       u_int   dirents;        /* root directory entries */
+       u_int   spf;            /* sectors per fat */
+       u_int   rdcl;           /* root directory start cluster */
+       u_int   lsnfat;         /* start of fat */
+       u_int   lsndir;         /* start of root dir */
+       u_int   lsndta;         /* start of data area */
+       u_int   fatsz;          /* FAT entry size */
+       u_int   xclus;          /* maximum cluster number */
+} DOS_FS;
+
+typedef struct {
+       DOS_FS *fs;             /* associated filesystem */
+       struct direntry de;     /* directory entry */
+       u_int   offset;         /* current offset */
+       u_int   c;              /* last cluster read */
+} DOS_FILE;
+
+/* Initial portion of DOS boot sector */
+typedef struct {
+       u_char  jmp[3];         /* usually 80x86 'jmp' opcode */
+       u_char  oem[8];         /* OEM name and version */
+       struct byte_bpb710 bpb; /* BPB */
+} DOS_BS;
+
+/* Supply missing "." and ".." root directory entries */
+static const char *const dotstr[2] = {".", ".."};
+static const struct direntry dot[2] = {
+       {".       ", "   ", ATTR_DIRECTORY,
+               0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+               {0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}},
+
+       {"..      ", "   ", ATTR_DIRECTORY,
+               0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0},
+               {0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}}
+};
+
+/* The usual conversion macros to avoid multiplication and division */
+#define bytsec(n)      ((n) >> SSHIFT)
+#define secbyt(s)      ((s) << SSHIFT)
+#define entsec(e)      ((e) >> DSHIFT)
+#define bytblk(fs, n)  ((n) >> (fs)->bshift)
+#define blkbyt(fs, b)  ((b) << (fs)->bshift)
+#define secblk(fs, s)  ((s) >> ((fs)->bshift - SSHIFT))
+#define blksec(fs, b)  ((b) << ((fs)->bshift - SSHIFT))
+
+/* Convert cluster number to offset within filesystem */
+#define blkoff(fs, b) (secbyt((fs)->lsndta) + blkbyt(fs, (b) - LOCLUS))
+
+/* Convert cluster number to logical sector number */
+#define blklsn(fs, b)  ((fs)->lsndta + blksec(fs, (b) - LOCLUS))
+
+/* Convert cluster number to offset within FAT */
+#define fatoff(sz, c)  ((sz) == 12 ? (c) + ((c) >> 1) :  \
+                        (sz) == 16 ? (c) << 1 :          \
+                        (c) << 2)
+
+/* Does cluster number reference a valid data cluster? */
+#define okclus(fs, c)  ((c) >= LOCLUS && (c) <= (fs)->xclus)
+
+/* Get start cluster from directory entry */
+#define stclus(sz, de)  ((sz) != 32 ? (u_int)getushort((de)->deStartCluster) : \
+                         ((u_int)getushort((de)->deHighClust) << 16) |  \
+                         (u_int)getushort((de)->deStartCluster))
+
+static int dosunmount(DOS_FS *);
+static int parsebs(DOS_FS *, DOS_BS *);
+static int namede(DOS_FS *, const char *, const struct direntry **);
+static int lookup(DOS_FS *, u_int, const char *, const struct direntry **);
+static void cp_xdnm(u_char *, struct winentry *);
+static void cp_sfn(u_char *, struct direntry *);
+static off_t fsize(DOS_FS *, struct direntry *);
+static int fatcnt(DOS_FS *, u_int);
+static int fatget(DOS_FS *, u_int *);
+static int fatend(u_int, u_int);
+static int ioread(DOS_FS *, u_int, void *, u_int);
+static int iobuf(DOS_FS *, u_int);
+static int ioget(struct open_file *, u_int, void *, u_int);
+
+#define strcasecmp(s1, s2) dos_strcasecmp(s1, s2)
+static int
+strcasecmp(const char *s1, const char *s2)
+{
+       char c1, c2;
+       #define TO_UPPER(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+       for (;;) {
+               c1 = *s1++;
+               c2 = *s2++;
+               if (TO_UPPER(c1) != TO_UPPER(c2))
+                       return 1;
+               if (c1 == 0)
+                       return 0;
+       }
+       #undef TO_UPPER
+}
+
+/*
+ * Mount DOS filesystem
+ */
+static int
+dos_mount(DOS_FS *fs, struct open_file *fd)
+{
+       int     err;
+
+       (void)memset(fs, 0, sizeof(DOS_FS));
+       fs->fd = fd;
+       if ((err = !(fs->buf = alloc(SECSIZ)) ? errno : 0) ||
+           (err = ioget(fs->fd, 0, fs->buf, 1)) ||
+           (err = parsebs(fs, (DOS_BS *)fs->buf))) {
+               (void) dosunmount(fs);
+               return err;
+       }
+       return 0;
+}
+
+#ifndef LIBSA_NO_FS_CLOSE
+/*
+ * Unmount mounted filesystem
+ */
+static int
+dos_unmount(DOS_FS *fs)
+{
+       int     err;
+
+       if (fs->links)
+               return EBUSY;
+       if ((err = dosunmount(fs)))
+               return err;
+       return 0;
+}
+#endif
+
+/*
+ * Common code shared by dos_mount() and dos_unmount()
+ */
+static int
+dosunmount(DOS_FS *fs)
+{
+       if (fs->buf)
+               dealloc(fs->buf, SECSIZ);
+       dealloc(fs, sizeof(DOS_FS));
+       return 0;
+}
+
+/*
+ * Open DOS file
+ */
+__compactcall int
+dosfs_open(const char *path, struct open_file *fd)
+{
+       const struct direntry *de;
+       DOS_FILE *f;
+       DOS_FS *fs;
+       u_int   size, clus;
+       int     err = 0;
+
+       /* Allocate mount structure, associate with open */
+       fs = alloc(sizeof(DOS_FS));
+
+       if ((err = dos_mount(fs, fd)))
+               goto out;
+
+       if ((err = namede(fs, path, &de)))
+               goto out;
+
+       clus = stclus(fs->fatsz, de);
+       size = getulong(de->deFileSize);
+
+       if ((!(de->deAttributes & ATTR_DIRECTORY) && (!clus != !size)) ||
+           ((de->deAttributes & ATTR_DIRECTORY) && size) ||
+           (clus && !okclus(fs, clus))) {
+               err = EINVAL;
+               goto out;
+       }
+
+       f = alloc(sizeof(DOS_FILE));
+#ifdef BOOTXX
+       /* due to __internal_memset_ causing all sorts of register spillage
+          (and being completely unoptimized for zeroing small amounts of
+          memory), if we hand-initialize the remaining members of f to zero,
+          the code size drops 68 bytes. This makes no sense, admittedly. */
+       f->offset = 0;
+       f->c = 0;
+#else
+       (void)memset(f, 0, sizeof(DOS_FILE));
+#endif
+       f->fs = fs;
+       fs->links++;
+       f->de = *de;
+       fd->f_fsdata = (void *)f;
+       fsmod = "msdos";
+
+out:
+       return err;
+}
+
+/*
+ * Read from file
+ */
+__compactcall int
+dosfs_read(struct open_file *fd, void *vbuf, size_t nbyte, size_t *resid)
+{
+       off_t   size;
+       u_int8_t *buf = vbuf;
+       u_int   nb, off, clus, c, cnt, n;
+       DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
+       int     err = 0;
+
+       nb = (u_int) nbyte;
+       if ((size = fsize(f->fs, &f->de)) == -1)
+               return EINVAL;
+       if (nb > (n = size - f->offset))
+               nb = n;
+       off = f->offset;
+       if ((clus = stclus(f->fs->fatsz, &f->de)))
+               off &= f->fs->bsize - 1;
+       c = f->c;
+       cnt = nb;
+       while (cnt) {
+               n = 0;
+               if (!c) {
+                       if ((c = clus))
+                               n = bytblk(f->fs, f->offset);
+               } else if (!off) {
+                       n++;
+               }
+               while (n--) {
+                       if ((err = fatget(f->fs, &c)))
+                               goto out;
+                       if (!okclus(f->fs, c)) {
+                               err = EINVAL;
+                               goto out;
+                       }
+               }
+               if (!clus || (n = f->fs->bsize - off) > cnt)
+                       n = cnt;
+               if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) :
+                               secbyt(f->fs->lsndir)) + off,
+                           buf, n)))
+                       goto out;
+               f->offset += n;
+               f->c = c;
+               off = 0;
+               buf += n;
+               cnt -= n;
+       }
+out:
+       if (resid)
+               *resid = nbyte - nb + cnt;
+       return err;
+}
+
+#ifndef LIBSA_NO_FS_WRITE
+/*
+ * Not implemented.
+ */
+__compactcall int
+dosfs_write(struct open_file *fd, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+/*
+ * Reposition within file
+ */
+__compactcall off_t
+dosfs_seek(struct open_file *fd, off_t offset, int whence)
+{
+       off_t   off;
+       u_int   size;
+       DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
+
+       size = getulong(f->de.deFileSize);
+       switch (whence) {
+       case SEEK_SET:
+               off = 0;
+               break;
+       case SEEK_CUR:
+               off = f->offset;
+               break;
+       case SEEK_END:
+               off = size;
+               break;
+       default:
+               return -1;
+       }
+       off += offset;
+       if (off < 0 || off > size)
+               return -1;
+       f->offset = (u_int) off;
+       f->c = 0;
+       return off;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+#ifndef LIBSA_NO_FS_CLOSE
+/*
+ * Close open file
+ */
+__compactcall int
+dosfs_close(struct open_file *fd)
+{
+       DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
+       DOS_FS *fs = f->fs;
+
+       f->fs->links--;
+       dealloc(f, sizeof(DOS_FILE));
+       dos_unmount(fs);
+       return 0;
+}
+#endif /* !LIBSA_NO_FS_CLOSE */
+
+/*
+ * Return some stat information on a file.
+ */
+__compactcall int
+dosfs_stat(struct open_file *fd, struct stat *sb)
+{
+       DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
+
+       /* only important stuff */
+       sb->st_mode = (f->de.deAttributes & ATTR_DIRECTORY) ?
+           (S_IFDIR | 0555) : (S_IFREG | 0444);
+       sb->st_nlink = 1;
+       sb->st_uid = 0;
+       sb->st_gid = 0;
+       if ((sb->st_size = fsize(f->fs, &f->de)) == -1)
+               return EINVAL;
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+dosfs_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by dosfs\n");
+       return;
+}
+#endif
+
+/*
+ * Parse DOS boot sector
+ */
+static int
+parsebs(DOS_FS *fs, DOS_BS *bs)
+{
+       u_int   sc;
+
+       if ((bs->jmp[0] != 0x69 &&
+               bs->jmp[0] != 0xe9 &&
+               (bs->jmp[0] != 0xeb || bs->jmp[2] != 0x90)) ||
+           bs->bpb.bpbMedia < 0xf0)
+               return EINVAL;
+       if (getushort(bs->bpb.bpbBytesPerSec) != SECSIZ)
+               return EINVAL;
+       if (!(fs->spc = bs->bpb.bpbSecPerClust) || fs->spc & (fs->spc - 1))
+               return EINVAL;
+       fs->bsize = secbyt(fs->spc);
+       fs->bshift = ffs(fs->bsize) - 1;
+       if ((fs->spf = getushort(bs->bpb.bpbFATsecs))) {
+               if (bs->bpb.bpbFATs != 2)
+                       return EINVAL;
+               if (!(fs->dirents = getushort(bs->bpb.bpbRootDirEnts)))
+                       return EINVAL;
+       } else {
+               if (!(fs->spf = getulong(bs->bpb.bpbBigFATsecs)))
+                       return EINVAL;
+               if (!bs->bpb.bpbFATs || bs->bpb.bpbFATs > 16)
+                       return EINVAL;
+               if ((fs->rdcl = getulong(bs->bpb.bpbRootClust)) < LOCLUS)
+                       return EINVAL;
+       }
+       if (!(fs->lsnfat = getushort(bs->bpb.bpbResSectors)))
+               return EINVAL;
+       fs->lsndir = fs->lsnfat + fs->spf * bs->bpb.bpbFATs;
+       fs->lsndta = fs->lsndir + entsec(fs->dirents);
+       if (!(sc = getushort(bs->bpb.bpbSectors)) &&
+           !(sc = getulong(bs->bpb.bpbHugeSectors)))
+               return EINVAL;
+       if (fs->lsndta > sc)
+               return EINVAL;
+       if ((fs->xclus = secblk(fs, sc - fs->lsndta) + 1) < LOCLUS)
+               return EINVAL;
+       fs->fatsz = fs->dirents ? fs->xclus < 0xff6 ? 12 : 16 : 32;
+       sc = (secbyt(fs->spf) << 1) / (fs->fatsz >> 2) - 1;
+       if (fs->xclus > sc)
+               fs->xclus = sc;
+       return 0;
+}
+
+/*
+ * Return directory entry from path
+ */
+static int
+namede(DOS_FS *fs, const char *path, const struct direntry **dep)
+{
+       char    name[256];
+       const struct direntry *de;
+       char   *s;
+       size_t  n;
+       int     err;
+
+       err = 0;
+       de = dot;
+       if (*path == '/')
+               path++;
+       while (*path) {
+               if (!(s = strchr(path, '/')))
+                       s = strchr(path, 0);
+               if ((n = s - path) > 255)
+                       return ENAMETOOLONG;
+               memcpy(name, path, n);
+               name[n] = 0;
+               path = s;
+               if (!(de->deAttributes & ATTR_DIRECTORY))
+                       return ENOTDIR;
+               if ((err = lookup(fs, stclus(fs->fatsz, de), name, &de)))
+                       return err;
+               if (*path == '/')
+                       path++;
+       }
+       *dep = de;
+       return 0;
+}
+
+/*
+ * Lookup path segment
+ */
+static int
+lookup(DOS_FS *fs, u_int clus, const char *name, const struct direntry **dep)
+{
+       static DOS_DIR *dir = NULL;
+       u_char  lfn[261];
+       u_char  sfn[13];
+       u_int   nsec, lsec, xdn, chk, sec, ent, x;
+       int     err = 0, ok, i;
+
+       if (!clus)
+               for (ent = 0; ent < 2; ent++)
+                       if (!strcasecmp(name, dotstr[ent])) {
+                               *dep = dot + ent;
+                               return 0;
+                       }
+
+       if (dir == NULL) {
+               dir = alloc(sizeof(DOS_DIR) * DEPSEC);
+               if (dir == NULL)
+                       return ENOMEM;
+       }
+
+       if (!clus && fs->fatsz == 32)
+               clus = fs->rdcl;
+       nsec = !clus ? entsec(fs->dirents) : fs->spc;
+       lsec = 0;
+       xdn = chk = 0;
+       for (;;) {
+               if (!clus && !lsec)
+                       lsec = fs->lsndir;
+               else if (okclus(fs, clus))
+                       lsec = blklsn(fs, clus);
+               else {
+                       err = EINVAL;
+                       goto out;
+               }
+               for (sec = 0; sec < nsec; sec++) {
+                       if ((err = ioget(fs->fd, lsec + sec, dir, 1)))
+                               goto out;
+                       for (ent = 0; ent < DEPSEC; ent++) {
+                               if (!*dir[ent].de.deName) {
+                                       err = ENOENT;
+                                       goto out;
+                               }
+                               if (*dir[ent].de.deName != 0xe5) {
+                                       if (dir[ent].de.deAttributes ==
+                                           ATTR_WIN95) {
+                                               x = dir[ent].xde.weCnt;
+                                               if (x & WIN_LAST ||
+                                                   (x + 1 == xdn &&
+                                                    dir[ent].xde.weChksum ==
+                                                    chk)) {
+                                                       if (x & WIN_LAST) {
+                                                               chk = dir[ent].xde.weChksum;
+                                                               x &= WIN_CNT;
+                                                       }
+                                                       if (x >= 1 && x <= 20) {
+                                                               cp_xdnm(lfn, &dir[ent].xde);
+                                                               xdn = x;
+                                                               continue;
+                                                       }
+                                               }
+                                       } else if (!(dir[ent].de.deAttributes &
+                                                    ATTR_VOLUME)) {
+                                               if ((ok = xdn == 1)) {
+                                                       for (x = 0, i = 0;
+                                                            i < 11; i++)
+                                                               x = ((((x & 1) << 7) | (x >> 1)) +
+                                                                   dir[ent].de.deName[i]) & 0xff;
+                                                       ok = chk == x &&
+                                                           !strcasecmp(name, (const char *)lfn);
+                                               }
+                                               if (!ok) {
+                                                       cp_sfn(sfn, &dir[ent].de);
+                                                       ok = !strcasecmp(name, (const char *)sfn);
+                                               }
+                                               if (ok) {
+                                                       *dep = &dir[ent].de;
+                                                       goto out2;
+                                               }
+                                       }
+                               }
+                               xdn = 0;
+                       }
+               }
+               if (!clus)
+                       break;
+               if ((err = fatget(fs, &clus)))
+                       goto out;
+               if (fatend(fs->fatsz, clus))
+                       break;
+       }
+       err = ENOENT;
+ out:
+       dealloc(dir, sizeof(DOS_DIR) * DEPSEC);
+       dir = NULL;
+ out2:
+       return err;
+}
+
+/*
+ * Copy name from extended directory entry
+ */
+static void
+cp_xdnm(u_char *lfn, struct winentry *xde)
+{
+       static const struct {
+               u_int   off;
+               u_int   dim;
+       } ix[3] = {
+               { offsetof(struct winentry, wePart1),
+                   sizeof(xde->wePart1) / 2 },
+               { offsetof(struct winentry, wePart2),
+                   sizeof(xde->wePart2) / 2 },
+               { offsetof(struct winentry, wePart3),
+                   sizeof(xde->wePart3) / 2 }
+       };
+       u_char *p;
+       u_int   n, x, c;
+
+       lfn += 13 * ((xde->weCnt & WIN_CNT) - 1);
+       for (n = 0; n < 3; n++)
+               for (p = (u_char *)xde + ix[n].off, x = ix[n].dim; x;
+                   p += 2, x--) {
+                       if ((c = getushort(p)) && (c < 32 || c > 127))
+                               c = '?';
+                       if (!(*lfn++ = c))
+                               return;
+               }
+       if (xde->weCnt & WIN_LAST)
+               *lfn = 0;
+}
+
+/*
+ * Copy short filename
+ */
+static void
+cp_sfn(u_char *sfn, struct direntry *de)
+{
+       u_char *p;
+       int     j, i;
+
+       p = sfn;
+       if (*de->deName != ' ') {
+               for (j = 7; de->deName[j] == ' '; j--);
+               for (i = 0; i <= j; i++)
+                       *p++ = de->deName[i];
+               if (*de->deExtension != ' ') {
+                       *p++ = '.';
+                       for (j = 2; de->deExtension[j] == ' '; j--);
+                       for (i = 0; i <= j; i++)
+                               *p++ = de->deExtension[i];
+               }
+       }
+       *p = 0;
+       if (*sfn == 5)
+               *sfn = 0xe5;
+}
+
+/*
+ * Return size of file in bytes
+ */
+static  off_t
+fsize(DOS_FS *fs, struct direntry *de)
+{
+       u_long  size;
+       u_int   c;
+       int     n;
+
+       if (!(size = getulong(de->deFileSize)) &&
+           de->deAttributes & ATTR_DIRECTORY) {
+               if (!(c = getushort(de->deStartCluster))) {
+                       size = fs->dirents * sizeof(struct direntry);
+               } else {
+                       if ((n = fatcnt(fs, c)) == -1)
+                               return n;
+                       size = blkbyt(fs, n);
+               }
+       }
+       return size;
+}
+
+/*
+ * Count number of clusters in chain
+ */
+static int
+fatcnt(DOS_FS *fs, u_int c)
+{
+       int     n;
+
+       for (n = 0; okclus(fs, c); n++)
+               if (fatget(fs, &c))
+                       return -1;
+       return fatend(fs->fatsz, c) ? n : -1;
+}
+
+/*
+ * Get next cluster in cluster chain
+ */
+static int
+fatget(DOS_FS *fs, u_int *c)
+{
+       u_char  buf[4];
+       u_int   x;
+       int     err;
+
+       err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf,
+           fs->fatsz != 32 ? 2 : 4);
+       if (err)
+               return err;
+       x = fs->fatsz != 32 ? getushort(buf) : getulong(buf);
+       *c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x;
+       return 0;
+}
+
+/*
+ * Is cluster an end-of-chain marker?
+ */
+static int
+fatend(u_int sz, u_int c)
+{
+       return c > (sz == 12 ? 0xff7U : sz == 16 ? 0xfff7U : 0xffffff7);
+}
+
+/*
+ * Offset-based I/O primitive
+ */
+static int
+ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte)
+{
+       char   *s;
+       u_int   off, n;
+       int     err;
+
+       s = buf;
+       if ((off = offset & (SECSIZ - 1))) {
+               offset -= off;
+               if ((err = iobuf(fs, bytsec(offset))))
+                       return err;
+               offset += SECSIZ;
+               if ((n = SECSIZ - off) > nbyte)
+                       n = nbyte;
+               memcpy(s, fs->buf + off, n);
+               s += n;
+               nbyte -= n;
+       }
+       n = nbyte & (SECSIZ - 1);
+       if (nbyte -= n) {
+               if ((err = ioget(fs->fd, bytsec(offset), s, bytsec(nbyte))))
+                       return err;
+               offset += nbyte;
+               s += nbyte;
+       }
+       if (n) {
+               if ((err = iobuf(fs, bytsec(offset))))
+                       return err;
+               memcpy(s, fs->buf, n);
+       }
+       return 0;
+}
+
+/*
+ * Buffered sector-based I/O primitive
+ */
+static int
+iobuf(DOS_FS *fs, u_int lsec)
+{
+       int     err;
+
+       if (fs->bufsec != lsec) {
+               if ((err = ioget(fs->fd, lsec, fs->buf, 1)))
+                       return err;
+               fs->bufsec = lsec;
+       }
+       return 0;
+}
+
+/*
+ * Sector-based I/O primitive
+ */
+static int
+ioget(struct open_file *fd, u_int lsec, void *buf, u_int nsec)
+{
+       size_t rsize;
+       int err;
+
+#ifndef LIBSA_NO_TWIDDLE
+       twiddle();
+#endif
+       err = DEV_STRATEGY(fd->f_dev)(fd->f_devdata, F_READ, lsec,
+           secbyt(nsec), buf, &rsize);
+       return err;
+}
diff --git a/sys/lib/libsa/dosfs.h b/sys/lib/libsa/dosfs.h
new file mode 100644 (file)
index 0000000..3c1ca9e
--- /dev/null
@@ -0,0 +1,30 @@
+/*     $NetBSD: dosfs.h,v 1.3 2005/12/11 12:24:46 christos Exp $       */
+
+/*
+ * Copyright (c) 1996, 1998 Robert Nordier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FS_DEF(dosfs);
diff --git a/sys/lib/libsa/errno.c b/sys/lib/libsa/errno.c
new file mode 100644 (file)
index 0000000..b1eae17
--- /dev/null
@@ -0,0 +1,36 @@
+/*     $NetBSD: errno.c,v 1.3 2005/12/11 12:24:46 christos Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)dev.c       8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+int errno;
diff --git a/sys/lib/libsa/ether.c b/sys/lib/libsa/ether.c
new file mode 100644 (file)
index 0000000..c70c381
--- /dev/null
@@ -0,0 +1,124 @@
+/*     $NetBSD: ether.c,v 1.22 2009/01/12 11:32:45 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "net.h"
+
+/* Caller must leave room for ethernet header in front!! */
+ssize_t
+sendether(struct iodesc *d, void *pkt, size_t len, u_char *dea, int etype)
+{
+       ssize_t n;
+       struct ether_header *eh;
+
+#ifdef ETHER_DEBUG
+       if (debug)
+               printf("sendether: called\n");
+#endif
+
+       eh = (struct ether_header *)pkt - 1;
+       len += sizeof(*eh);
+
+       MACPY(d->myea, eh->ether_shost);                /* by byte */
+       MACPY(dea, eh->ether_dhost);                    /* by byte */
+       eh->ether_type = htons(etype);
+
+       n = netif_put(d, eh, len);
+       if (n == -1 || (size_t)n < sizeof(*eh))
+               return -1;
+
+       n -= sizeof(*eh);
+       return n;
+}
+
+/*
+ * Get a packet of any Ethernet type, with our address or
+ * the broadcast address.  Save the Ether type in arg 5.
+ * NOTE: Caller must leave room for the Ether header.
+ */
+ssize_t
+readether(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft,
+       u_int16_t *etype)
+{
+       ssize_t n;
+       struct ether_header *eh;
+
+#ifdef ETHER_DEBUG
+       if (debug)
+               printf("readether: called\n");
+#endif
+
+       eh = (struct ether_header *)pkt - 1;
+       len += sizeof(*eh);
+
+       n = netif_get(d, eh, len, tleft);
+       if (n == -1 || (size_t)n < sizeof(*eh))
+               return -1;
+
+       /* Validate Ethernet address. */
+       if (memcmp(d->myea, eh->ether_dhost, 6) != 0 &&
+           memcmp(bcea, eh->ether_dhost, 6) != 0) {
+#ifdef ETHER_DEBUG
+               if (debug)
+                       printf("readether: not ours (ea=%s)\n",
+                           ether_sprintf(eh->ether_dhost));
+#endif
+               return -1;
+       }
+       *etype = ntohs(eh->ether_type);
+
+       n -= sizeof(*eh);
+       return n;
+}
diff --git a/sys/lib/libsa/ether_sprintf.c b/sys/lib/libsa/ether_sprintf.c
new file mode 100644 (file)
index 0000000..ae1fe92
--- /dev/null
@@ -0,0 +1,73 @@
+/*     $NetBSD: ether_sprintf.c,v 1.6 2007/11/24 13:20:55 isaki Exp $  */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "net.h"
+
+/*
+ * Convert Ethernet address to printable (loggable) representation.
+ */
+char *
+ether_sprintf(const u_char *ap)
+{
+       int i;
+       static char etherbuf[18];
+       char *cp = etherbuf;
+
+       for (i = 0; i < 6; i++) {
+               *cp++ = hexdigits[*ap >> 4];
+               *cp++ = hexdigits[*ap++ & 0xf];
+               *cp++ = ':';
+       }
+       *--cp = 0;
+       return etherbuf;
+}
diff --git a/sys/lib/libsa/exec.c b/sys/lib/libsa/exec.c
new file mode 100644 (file)
index 0000000..325a68f
--- /dev/null
@@ -0,0 +1,165 @@
+/*     $NetBSD: exec.c,v 1.28 2009/12/29 20:21:46 elad Exp $   */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#ifndef SA_EXEC_ANYOWNER
+#include <sys/stat.h>
+#endif
+#include <sys/exec_aout.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+
+void
+exec(char *path, char *loadaddr, int howto)
+{
+#ifndef SA_EXEC_ANYOWNER
+       struct stat sb;
+#endif
+       struct exec x;
+       int io, i;
+       char *addr, *ssym, *esym;
+
+       io = open(path, 0);
+       if (io < 0)
+               return;
+
+#ifndef SA_EXEC_ANYOWNER
+       (void) fstat(io, &sb);
+       if (sb.st_uid || (sb.st_mode & 2)) {
+               printf("non-secure file, will not load\n");
+               close(io);
+               errno = EPERM;
+               return;
+       }
+#endif
+
+       i = read(io, (char *)&x, sizeof(x));
+       if (i != sizeof(x) || N_BADMAG(x)) {
+               errno = EFTYPE;
+               return;
+       }
+
+       /* Text */
+       printf("%ld", x.a_text);
+       addr = loadaddr;
+       if (N_GETMAGIC(x) == ZMAGIC) {
+               (void)memcpy(addr, &x, sizeof(x));
+               addr += sizeof(x);
+               x.a_text -= sizeof(x);
+       }
+       if (read(io, (char *)addr, x.a_text) != (ssize_t)x.a_text)
+               goto shread;
+       addr += x.a_text;
+       if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC)
+               while ((long)addr & (N_PAGSIZ(x) - 1))
+                       *addr++ = 0;
+
+       /* Data */
+       printf("+%ld", x.a_data);
+       if (read(io, addr, x.a_data) != (ssize_t)x.a_data)
+               goto shread;
+       addr += x.a_data;
+
+       /* Bss */
+       printf("+%ld", x.a_bss);
+       for (i = 0; i < (int)x.a_bss; i++)
+               *addr++ = 0;
+
+       /* Symbols */
+       ssym = addr;
+       (void)memcpy(addr, &x.a_syms, sizeof(x.a_syms));
+       addr += sizeof(x.a_syms);
+       if (x.a_syms) {
+               printf("+[%ld", x.a_syms);
+               if (read(io, addr, x.a_syms) != (ssize_t)x.a_syms)
+                       goto shread;
+               addr += x.a_syms;
+       }
+
+       i = 0;
+       if (x.a_syms && read(io, &i, sizeof(int)) != sizeof(int))
+               goto shread;
+
+       (void)memcpy(addr, &i, sizeof(int));
+       if (i) {
+               i -= sizeof(int);
+               addr += sizeof(int);
+               if (read(io, addr, i) != i)
+                       goto shread;
+               addr += i;
+       }
+
+       if (x.a_syms) {
+               /* and that many bytes of (debug symbols?) */
+               printf("+%d]", i);
+       }
+
+       close(io);
+
+#define        round_to_size(x) \
+       (((int)(x) + sizeof(int) - 1) & ~(sizeof(int) - 1))
+       esym = (char *)round_to_size(addr - loadaddr);
+#undef round_to_size
+
+       /* and note the end address of all this */
+       printf(" total=0x%lx\n", (u_long)addr);
+
+       /*
+        * Machine-dependent code must now adjust the
+        * entry point.  This used to be done here,
+        * but some systems may need to relocate the
+        * loaded file before jumping to it, and the
+        * displayed start address would be wrong.
+        */
+
+#ifdef EXEC_DEBUG
+       printf("ssym=0x%x esym=0x%x\n", ssym, esym);
+       printf("\n\nReturn to boot...\n");
+       getchar();
+#endif
+
+       machdep_start((char *)x.a_entry, howto, loadaddr, ssym, esym);
+
+       /* exec failed */
+       errno = ENOEXEC;
+       return;
+
+shread:
+       close(io);
+       errno = EIO;
+       return;
+}
diff --git a/sys/lib/libsa/exit.c b/sys/lib/libsa/exit.c
new file mode 100644 (file)
index 0000000..cc7f1e2
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $NetBSD: exit.c,v 1.17 2007/11/24 13:20:55 isaki Exp $  */
+
+/*-
+ *  Copyright (c) 1993 John Brezak
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "stand.h"
+
+void
+exit(int arg)
+{
+       panic("exit");
+       /*NOTREACHED*/
+}
diff --git a/sys/lib/libsa/ext2fs.c b/sys/lib/libsa/ext2fs.c
new file mode 100644 (file)
index 0000000..dc3b49f
--- /dev/null
@@ -0,0 +1,1072 @@
+/*     $NetBSD: ext2fs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $      */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * Copyright (c) 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: David Golub
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ *     Stand-alone file reading package for Ext2 file system.
+ */
+
+/* #define EXT2FS_DEBUG */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <ufs/ext2fs/ext2fs_dinode.h>
+#include <ufs/ext2fs/ext2fs_dir.h>
+#include <ufs/ext2fs/ext2fs.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "ext2fs.h"
+
+#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
+#define LIBSA_NO_FS_SYMLINK
+#endif
+
+#if defined(LIBSA_NO_TWIDDLE)
+#define twiddle()
+#endif
+
+#ifndef indp_t
+#define indp_t         int32_t
+#endif
+typedef uint32_t       ino32_t;
+#ifndef FSBTODB
+#define FSBTODB(fs, indp) fsbtodb(fs, indp)
+#endif
+
+/*
+ * To avoid having a lot of filesystem-block sized buffers lurking (which
+ * could be 32k) we only keep a few entries of the indirect block map.
+ * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
+ * ~13 times pulling in a 6M kernel.
+ * The cache size must be smaller than the smallest filesystem block,
+ * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
+ */
+#define LN2_IND_CACHE_SZ       6
+#define IND_CACHE_SZ           (1 << LN2_IND_CACHE_SZ)
+#define IND_CACHE_MASK         (IND_CACHE_SZ - 1)
+
+/*
+ * In-core open file.
+ */
+struct file {
+       off_t           f_seekp;        /* seek pointer */
+       struct m_ext2fs *f_fs;          /* pointer to super-block */
+       struct ext2fs_dinode    f_di;           /* copy of on-disk inode */
+       uint            f_nishift;      /* for blocks in indirect block */
+       indp_t          f_ind_cache_block;
+       indp_t          f_ind_cache[IND_CACHE_SZ];
+
+       char            *f_buf;         /* buffer for data block */
+       size_t          f_buf_size;     /* size of data block */
+       daddr_t         f_buf_blkno;    /* block number of data block */
+};
+
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+       entry_t *e_next;
+       ino32_t e_ino;
+       uint8_t e_type;
+       char    e_name[1];
+};
+
+static const char    *const typestr[] = {
+       "unknown",
+       "REG",
+       "DIR",
+       "CHR",
+       "BLK",
+       "FIFO",
+       "SOCK",
+       "LNK"
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+       char fc, pc;
+
+       do {
+               fc = *fname++;
+               pc = *pattern++;
+               if (!fc && !pc)
+                       return 1;
+               if (pc == '?' && fc)
+                       pc = fc;
+       } while (fc == pc);
+
+       if (pc != '*')
+               return 0;
+       /*
+        * Too hard (and unnecessary really) too check for "*?name" etc....
+        * "**" will look for a '*' and "*?" a '?'
+        */
+       pc = *pattern++;
+       if (!pc)
+               return 1;
+       while ((fname = strchr(fname, pc)))
+               if (fn_match(++fname, pattern))
+                       return 1;
+       return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
+static int read_inode(ino32_t, struct open_file *);
+static int block_map(struct open_file *, indp_t, indp_t *);
+static int buf_read_file(struct open_file *, char **, size_t *);
+static int search_directory(const char *, int, struct open_file *, ino32_t *);
+static int read_sblock(struct open_file *, struct m_ext2fs *);
+static int read_gdblock(struct open_file *, struct m_ext2fs *);
+#ifdef EXT2FS_DEBUG
+static void dump_sblock(struct m_ext2fs *);
+#endif
+
+/*
+ * Read a new inode into a file structure.
+ */
+static int
+read_inode(ino32_t inumber, struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct m_ext2fs *fs = fp->f_fs;
+       char *buf;
+       size_t rsize;
+       int rc;
+       daddr_t inode_sector;
+       struct ext2fs_dinode *dip;
+
+       inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
+
+       /*
+        * Read inode and save it.
+        */
+       buf = fp->f_buf;
+       twiddle();
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+           inode_sector, fs->e2fs_bsize, buf, &rsize);
+       if (rc)
+               return rc;
+       if (rsize != fs->e2fs_bsize)
+               return EIO;
+
+       dip = (struct ext2fs_dinode *)(buf +
+           EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, inumber));
+       e2fs_iload(dip, &fp->f_di);
+
+       /*
+        * Clear out the old buffers
+        */
+       fp->f_ind_cache_block = ~0;
+       fp->f_buf_blkno = -1;
+       return rc;
+}
+
+/*
+ * Given an offset in a file, find the disk block number that
+ * contains that block.
+ */
+static int
+block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct m_ext2fs *fs = fp->f_fs;
+       uint level;
+       indp_t ind_cache;
+       indp_t ind_block_num;
+       size_t rsize;
+       int rc;
+       indp_t *buf = (void *)fp->f_buf;
+
+       /*
+        * Index structure of an inode:
+        *
+        * e2di_blocks[0..NDADDR-1]
+        *                      hold block numbers for blocks
+        *                      0..NDADDR-1
+        *
+        * e2di_blocks[NDADDR+0]
+        *                      block NDADDR+0 is the single indirect block
+        *                      holds block numbers for blocks
+        *                      NDADDR .. NDADDR + NINDIR(fs)-1
+        *
+        * e2di_blocks[NDADDR+1]
+        *                      block NDADDR+1 is the double indirect block
+        *                      holds block numbers for INDEX blocks for blocks
+        *                      NDADDR + NINDIR(fs) ..
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
+        *
+        * e2di_blocks[NDADDR+2]
+        *                      block NDADDR+2 is the triple indirect block
+        *                      holds block numbers for double-indirect
+        *                      blocks for blocks
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2
+        *                              + NINDIR(fs)**3 - 1
+        */
+
+       if (file_block < NDADDR) {
+               /* Direct block. */
+               *disk_block_p = fs2h32(fp->f_di.e2di_blocks[file_block]);
+               return 0;
+       }
+
+       file_block -= NDADDR;
+
+       ind_cache = file_block >> LN2_IND_CACHE_SZ;
+       if (ind_cache == fp->f_ind_cache_block) {
+               *disk_block_p =
+                   fs2h32(fp->f_ind_cache[file_block & IND_CACHE_MASK]);
+               return 0;
+       }
+
+       for (level = 0;;) {
+               level += fp->f_nishift;
+               if (file_block < (indp_t)1 << level)
+                       break;
+               if (level > NIADDR * fp->f_nishift)
+                       /* Block number too high */
+                       return EFBIG;
+               file_block -= (indp_t)1 << level;
+       }
+
+       ind_block_num =
+           fs2h32(fp->f_di.e2di_blocks[NDADDR + (level / fp->f_nishift - 1)]);
+
+       for (;;) {
+               level -= fp->f_nishift;
+               if (ind_block_num == 0) {
+                       *disk_block_p = 0;      /* missing */
+                       return 0;
+               }
+
+               twiddle();
+               /*
+                * If we were feeling brave, we could work out the number
+                * of the disk sector and read a single disk sector instead
+                * of a filesystem block.
+                * However we don't do this very often anyway...
+                */
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                       FSBTODB(fp->f_fs, ind_block_num), fs->e2fs_bsize,
+                       buf, &rsize);
+               if (rc)
+                       return rc;
+               if (rsize != fs->e2fs_bsize)
+                       return EIO;
+               ind_block_num = fs2h32(buf[file_block >> level]);
+               if (level == 0)
+                       break;
+               file_block &= (1 << level) - 1;
+       }
+
+       /* Save the part of the block that contains this sector */
+       memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
+           IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
+       fp->f_ind_cache_block = ind_cache;
+
+       *disk_block_p = ind_block_num;
+
+       return 0;
+}
+
+/*
+ * Read a portion of a file into an internal buffer.
+ * Return the location in the buffer and the amount in the buffer.
+ */
+static int
+buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct m_ext2fs *fs = fp->f_fs;
+       long off;
+       indp_t file_block;
+       indp_t disk_block;
+       size_t block_size;
+       int rc;
+
+       off = blkoff(fs, fp->f_seekp);
+       file_block = lblkno(fs, fp->f_seekp);
+       block_size = fs->e2fs_bsize;    /* no fragment */
+
+       if (file_block != fp->f_buf_blkno) {
+               rc = block_map(f, file_block, &disk_block);
+               if (rc)
+                       return rc;
+
+               if (disk_block == 0) {
+                       memset(fp->f_buf, 0, block_size);
+                       fp->f_buf_size = block_size;
+               } else {
+                       twiddle();
+                       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                               FSBTODB(fs, disk_block),
+                               block_size, fp->f_buf, &fp->f_buf_size);
+                       if (rc)
+                               return rc;
+               }
+
+               fp->f_buf_blkno = file_block;
+       }
+
+       /*
+        * Return address of byte in buffer corresponding to
+        * offset, and size of remainder of buffer after that
+        * byte.
+        */
+       *buf_p = fp->f_buf + off;
+       *size_p = block_size - off;
+
+       /*
+        * But truncate buffer at end of file.
+        */
+       /* XXX should handle LARGEFILE */
+       if (*size_p > fp->f_di.e2di_size - fp->f_seekp)
+               *size_p = fp->f_di.e2di_size - fp->f_seekp;
+
+       return 0;
+}
+
+/*
+ * Search a directory for a name and return its
+ * inode number.
+ */
+static int
+search_directory(const char *name, int length, struct open_file *f,
+       ino32_t *inumber_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct ext2fs_direct *dp;
+       struct ext2fs_direct *edp;
+       char *buf;
+       size_t buf_size;
+       int namlen;
+       int rc;
+
+       fp->f_seekp = 0;
+       /* XXX should handle LARGEFILE */
+       while (fp->f_seekp < (off_t)fp->f_di.e2di_size) {
+               rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       return rc;
+
+               dp = (struct ext2fs_direct *)buf;
+               edp = (struct ext2fs_direct *)(buf + buf_size);
+               for (; dp < edp;
+                   dp = (void *)((char *)dp + fs2h16(dp->e2d_reclen))) {
+                       if (fs2h16(dp->e2d_reclen) <= 0)
+                               break;
+                       if (fs2h32(dp->e2d_ino) == (ino32_t)0)
+                               continue;
+                       namlen = dp->e2d_namlen;
+                       if (namlen == length &&
+                           !memcmp(name, dp->e2d_name, length)) {
+                               /* found entry */
+                               *inumber_p = fs2h32(dp->e2d_ino);
+                               return 0;
+                       }
+               }
+               fp->f_seekp += buf_size;
+       }
+       return ENOENT;
+}
+
+int
+read_sblock(struct open_file *f, struct m_ext2fs *fs)
+{
+       static uint8_t sbbuf[SBSIZE];
+       struct ext2fs ext2fs;
+       size_t buf_size;
+       int rc;
+
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+           SBOFF / DEV_BSIZE, SBSIZE, sbbuf, &buf_size);
+       if (rc)
+               return rc;
+
+       if (buf_size != SBSIZE)
+               return EIO;
+
+       e2fs_sbload((void *)sbbuf, &ext2fs);
+       if (ext2fs.e2fs_magic != E2FS_MAGIC)
+               return EINVAL;
+       if (ext2fs.e2fs_rev > E2FS_REV1 ||
+           (ext2fs.e2fs_rev == E2FS_REV1 &&
+            (ext2fs.e2fs_first_ino != EXT2_FIRSTINO ||
+            (ext2fs.e2fs_inode_size != 128 && ext2fs.e2fs_inode_size != 256) ||
+             ext2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP))) {
+               return ENODEV;
+       }
+
+       e2fs_sbload((void *)sbbuf, &fs->e2fs);
+       /* compute in-memory m_ext2fs values */
+       fs->e2fs_ncg =
+           howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
+           fs->e2fs.e2fs_bpg);
+       /* XXX assume hw bsize = 512 */
+       fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
+       fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize;
+       fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
+       fs->e2fs_qbmask = fs->e2fs_bsize - 1;
+       fs->e2fs_bmask = ~fs->e2fs_qbmask;
+       fs->e2fs_ngdb =
+           howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd));
+       fs->e2fs_ipb = fs->e2fs_bsize / ext2fs.e2fs_inode_size;
+       fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
+
+       return 0;
+}
+
+int
+read_gdblock(struct open_file *f, struct m_ext2fs *fs)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       size_t rsize;
+       uint gdpb;
+       int i, rc;
+
+       gdpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+
+       for (i = 0; i < fs->e2fs_ngdb; i++) {
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                   FSBTODB(fs, fs->e2fs.e2fs_first_dblock +
+                   1 /* superblock */ + i),
+                   fs->e2fs_bsize, fp->f_buf, &rsize);
+               if (rc)
+                       return rc;
+               if (rsize != fs->e2fs_bsize)
+                       return EIO;
+
+               e2fs_cgload((struct ext2_gd *)fp->f_buf,
+                   &fs->e2fs_gd[i * gdpb],
+                   (i == (fs->e2fs_ngdb - 1)) ?
+                   (fs->e2fs_ncg - gdpb * i) * sizeof(struct ext2_gd):
+                   fs->e2fs_bsize);
+       }
+
+       return 0;
+}
+
+
+/*
+ * Open a file.
+ */
+__compactcall int
+ext2fs_open(const char *path, struct open_file *f)
+{
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       const char *cp, *ncp;
+       int c;
+#endif
+       ino32_t inumber;
+       struct file *fp;
+       struct m_ext2fs *fs;
+       int rc;
+#ifndef LIBSA_NO_FS_SYMLINK
+       ino32_t parent_inumber;
+       int nlinks = 0;
+       char namebuf[MAXPATHLEN+1];
+       char *buf;
+#endif
+
+       /* allocate file system specific data structure */
+       fp = alloc(sizeof(struct file));
+       memset(fp, 0, sizeof(struct file));
+       f->f_fsdata = (void *)fp;
+
+       /* allocate space and read super block */
+       fs = alloc(sizeof(*fs));
+       memset(fs, 0, sizeof(*fs));
+       fp->f_fs = fs;
+       twiddle();
+
+       rc = read_sblock(f, fs);
+       if (rc)
+               goto out;
+
+#ifdef EXT2FS_DEBUG
+       dump_sblock(fs);
+#endif
+
+       /* alloc a block sized buffer used for all fs transfers */
+       fp->f_buf = alloc(fs->e2fs_bsize);
+
+       /* read group descriptor blocks */
+       fs->e2fs_gd = alloc(sizeof(struct ext2_gd) * fs->e2fs_ncg);
+       rc = read_gdblock(f, fs);
+       if (rc)
+               goto out;
+
+       /*
+        * Calculate indirect block levels.
+        */
+       {
+               indp_t mult;
+               int ln2;
+
+               /*
+                * We note that the number of indirect blocks is always
+                * a power of 2.  This lets us use shifts and masks instead
+                * of divide and remainder and avoinds pulling in the
+                * 64bit division routine into the boot code.
+                */
+               mult = NINDIR(fs);
+#ifdef DEBUG
+               if (!powerof2(mult)) {
+                       /* Hummm was't a power of 2 */
+                       rc = EINVAL;
+                       goto out;
+               }
+#endif
+               for (ln2 = 0; mult != 1; ln2++)
+                       mult >>= 1;
+
+               fp->f_nishift = ln2;
+       }
+
+       inumber = EXT2_ROOTINO;
+       if ((rc = read_inode(inumber, f)) != 0)
+               goto out;
+
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       cp = path;
+       while (*cp) {
+
+               /*
+                * Remove extra separators
+                */
+               while (*cp == '/')
+                       cp++;
+               if (*cp == '\0')
+                       break;
+
+               /*
+                * Check that current node is a directory.
+                */
+               if ((fp->f_di.e2di_mode & EXT2_IFMT) != EXT2_IFDIR) {
+                       rc = ENOTDIR;
+                       goto out;
+               }
+
+               /*
+                * Get next component of path name.
+                */
+               ncp = cp;
+               while ((c = *cp) != '\0' && c != '/')
+                       cp++;
+
+               /*
+                * Look up component in current directory.
+                * Save directory inumber in case we find a
+                * symbolic link.
+                */
+#ifndef LIBSA_NO_FS_SYMLINK
+               parent_inumber = inumber;
+#endif
+               rc = search_directory(ncp, cp - ncp, f, &inumber);
+               if (rc)
+                       goto out;
+
+               /*
+                * Open next component.
+                */
+               if ((rc = read_inode(inumber, f)) != 0)
+                       goto out;
+
+#ifndef LIBSA_NO_FS_SYMLINK
+               /*
+                * Check for symbolic link.
+                */
+               if ((fp->f_di.e2di_mode & EXT2_IFMT) == EXT2_IFLNK) {
+                       /* XXX should handle LARGEFILE */
+                       int link_len = fp->f_di.e2di_size;
+                       int len;
+
+                       len = strlen(cp);
+
+                       if (link_len + len > MAXPATHLEN ||
+                           ++nlinks > MAXSYMLINKS) {
+                               rc = ENOENT;
+                               goto out;
+                       }
+
+                       memmove(&namebuf[link_len], cp, len + 1);
+
+                       if (link_len < EXT2_MAXSYMLINKLEN) {
+                               memcpy(namebuf, fp->f_di.e2di_blocks, link_len);
+                       } else {
+                               /*
+                                * Read file for symbolic link
+                                */
+                               size_t buf_size;
+                               indp_t  disk_block;
+
+                               buf = fp->f_buf;
+                               rc = block_map(f, (indp_t)0, &disk_block);
+                               if (rc)
+                                       goto out;
+
+                               twiddle();
+                               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
+                                       F_READ, FSBTODB(fs, disk_block),
+                                       fs->e2fs_bsize, buf, &buf_size);
+                               if (rc)
+                                       goto out;
+
+                               memcpy(namebuf, buf, link_len);
+                       }
+
+                       /*
+                        * If relative pathname, restart at parent directory.
+                        * If absolute pathname, restart at root.
+                        */
+                       cp = namebuf;
+                       if (*cp != '/')
+                               inumber = parent_inumber;
+                       else
+                               inumber = (ino32_t)EXT2_ROOTINO;
+
+                       if ((rc = read_inode(inumber, f)) != 0)
+                               goto out;
+               }
+#endif /* !LIBSA_NO_FS_SYMLINK */
+       }
+
+       /*
+        * Found terminal component.
+        */
+       rc = 0;
+
+#else /* !LIBSA_FS_SINGLECOMPONENT */
+
+       /* look up component in the current (root) directory */
+       rc = search_directory(path, strlen(path), f, &inumber);
+       if (rc)
+               goto out;
+
+       /* open it */
+       rc = read_inode(inumber, f);
+
+#endif /* !LIBSA_FS_SINGLECOMPONENT */
+
+       fp->f_seekp = 0;                /* reset seek pointer */
+
+out:
+       if (rc)
+               ext2fs_close(f);
+       else {
+               fsmod = "ext2fs";
+               fsmod2 = "ffs";
+       }
+       return rc;
+}
+
+__compactcall int
+ext2fs_close(struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       f->f_fsdata = NULL;
+       if (fp == NULL)
+               return 0;
+
+       if (fp->f_fs->e2fs_gd)
+               dealloc(fp->f_fs->e2fs_gd,
+                   sizeof(struct ext2_gd) * fp->f_fs->e2fs_ncg);
+       if (fp->f_buf)
+               dealloc(fp->f_buf, fp->f_fs->e2fs_bsize);
+       dealloc(fp->f_fs, sizeof(*fp->f_fs));
+       dealloc(fp, sizeof(struct file));
+       return 0;
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+__compactcall int
+ext2fs_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       size_t csize;
+       char *buf;
+       size_t buf_size;
+       int rc = 0;
+       char *addr = start;
+
+       while (size != 0) {
+               /* XXX should handle LARGEFILE */
+               if (fp->f_seekp >= (off_t)fp->f_di.e2di_size)
+                       break;
+
+               rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       break;
+
+               csize = size;
+               if (csize > buf_size)
+                       csize = buf_size;
+
+               memcpy(addr, buf, csize);
+
+               fp->f_seekp += csize;
+               addr += csize;
+               size -= csize;
+       }
+       if (resid)
+               *resid = size;
+       return rc;
+}
+
+/*
+ * Not implemented.
+ */
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+ext2fs_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+ext2fs_seek(struct open_file *f, off_t offset, int where)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               fp->f_seekp = offset;
+               break;
+       case SEEK_CUR:
+               fp->f_seekp += offset;
+               break;
+       case SEEK_END:
+               /* XXX should handle LARGEFILE */
+               fp->f_seekp = fp->f_di.e2di_size - offset;
+               break;
+       default:
+               return -1;
+       }
+       return fp->f_seekp;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+__compactcall int
+ext2fs_stat(struct open_file *f, struct stat *sb)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       /* only important stuff */
+       memset(sb, 0, sizeof *sb);
+       sb->st_mode = fp->f_di.e2di_mode;
+       sb->st_uid = fp->f_di.e2di_uid;
+       sb->st_gid = fp->f_di.e2di_gid;
+       /* XXX should handle LARGEFILE */
+       sb->st_size = fp->f_di.e2di_size;
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ext2fs_ls(struct open_file *f, const char *pattern)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       size_t block_size = fp->f_fs->e2fs_bsize;
+       char *buf;
+       size_t buf_size;
+       entry_t *names = 0, *n, **np;
+
+       fp->f_seekp = 0;
+       while (fp->f_seekp < (off_t)fp->f_di.e2di_size) {
+               struct ext2fs_direct  *dp, *edp;
+               int rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       goto out;
+               if (buf_size != block_size || buf_size == 0)
+                       goto out;
+
+               dp = (struct ext2fs_direct *)buf;
+               edp = (struct ext2fs_direct *)(buf + buf_size);
+
+               for (; dp < edp;
+                    dp = (void *)((char *)dp + fs2h16(dp->e2d_reclen))) {
+                       const char *t;
+
+                       if (fs2h16(dp->e2d_reclen) <= 0)
+                               goto out;
+
+                       if (fs2h32(dp->e2d_ino) == 0)
+                               continue;
+
+                       if (dp->e2d_type >= NELEM(typestr) ||
+                           !(t = typestr[dp->e2d_type])) {
+                               /*
+                                * This does not handle "old"
+                                * filesystems properly. On little
+                                * endian machines, we get a bogus
+                                * type name if the namlen matches a
+                                * valid type identifier. We could
+                                * check if we read namlen "0" and
+                                * handle this case specially, if
+                                * there were a pressing need...
+                                */
+                               printf("bad dir entry\n");
+                               goto out;
+                       }
+                       if (pattern && !fn_match(dp->e2d_name, pattern))
+                               continue;
+                       n = alloc(sizeof *n + strlen(dp->e2d_name));
+                       if (!n) {
+                               printf("%d: %s (%s)\n",
+                                       fs2h32(dp->e2d_ino), dp->e2d_name, t);
+                               continue;
+                       }
+                       n->e_ino = fs2h32(dp->e2d_ino);
+                       n->e_type = dp->e2d_type;
+                       strcpy(n->e_name, dp->e2d_name);
+                       for (np = &names; *np; np = &(*np)->e_next) {
+                               if (strcmp(n->e_name, (*np)->e_name) < 0)
+                                       break;
+                       }
+                       n->e_next = *np;
+                       *np = n;
+               }
+               fp->f_seekp += buf_size;
+       }
+
+       if (names) {
+               entry_t *p_names = names;
+               do {
+                       n = p_names;
+                       printf("%d: %s (%s)\n",
+                               n->e_ino, n->e_name, typestr[n->e_type]);
+                       p_names = n->e_next;
+               } while (p_names);
+       } else {
+               printf("not found\n");
+       }
+out:
+       if (names) {
+               do {
+                       n = names;
+                       names = n->e_next;
+                       dealloc(n, 0);
+               } while (names);
+       }
+       return;
+}
+#endif
+
+/*
+ * byte swap functions for big endian machines
+ * (ext2fs is always little endian)
+ *
+ * XXX: We should use src/sys/ufs/ext2fs/ext2fs_bswap.c
+ */
+
+/* These functions are only needed if native byte order is not big endian */
+#if BYTE_ORDER == BIG_ENDIAN
+void
+e2fs_sb_bswap(struct ext2fs *old, struct ext2fs *new)
+{
+
+       /* preserve unused fields */
+       memcpy(new, old, sizeof(struct ext2fs));
+       new->e2fs_icount        =       bswap32(old->e2fs_icount);
+       new->e2fs_bcount        =       bswap32(old->e2fs_bcount);
+       new->e2fs_rbcount       =       bswap32(old->e2fs_rbcount);
+       new->e2fs_fbcount       =       bswap32(old->e2fs_fbcount);
+       new->e2fs_ficount       =       bswap32(old->e2fs_ficount);
+       new->e2fs_first_dblock  =       bswap32(old->e2fs_first_dblock);
+       new->e2fs_log_bsize     =       bswap32(old->e2fs_log_bsize);
+       new->e2fs_fsize         =       bswap32(old->e2fs_fsize);
+       new->e2fs_bpg           =       bswap32(old->e2fs_bpg);
+       new->e2fs_fpg           =       bswap32(old->e2fs_fpg);
+       new->e2fs_ipg           =       bswap32(old->e2fs_ipg);
+       new->e2fs_mtime         =       bswap32(old->e2fs_mtime);
+       new->e2fs_wtime         =       bswap32(old->e2fs_wtime);
+       new->e2fs_mnt_count     =       bswap16(old->e2fs_mnt_count);
+       new->e2fs_max_mnt_count =       bswap16(old->e2fs_max_mnt_count);
+       new->e2fs_magic         =       bswap16(old->e2fs_magic);
+       new->e2fs_state         =       bswap16(old->e2fs_state);
+       new->e2fs_beh           =       bswap16(old->e2fs_beh);
+       new->e2fs_minrev        =       bswap16(old->e2fs_minrev);
+       new->e2fs_lastfsck      =       bswap32(old->e2fs_lastfsck);
+       new->e2fs_fsckintv      =       bswap32(old->e2fs_fsckintv);
+       new->e2fs_creator       =       bswap32(old->e2fs_creator);
+       new->e2fs_rev           =       bswap32(old->e2fs_rev);
+       new->e2fs_ruid          =       bswap16(old->e2fs_ruid);
+       new->e2fs_rgid          =       bswap16(old->e2fs_rgid);
+       new->e2fs_first_ino     =       bswap32(old->e2fs_first_ino);
+       new->e2fs_inode_size    =       bswap16(old->e2fs_inode_size);
+       new->e2fs_block_group_nr =      bswap16(old->e2fs_block_group_nr);
+       new->e2fs_features_compat =     bswap32(old->e2fs_features_compat);
+       new->e2fs_features_incompat =   bswap32(old->e2fs_features_incompat);
+       new->e2fs_features_rocompat =   bswap32(old->e2fs_features_rocompat);
+       new->e2fs_algo          =       bswap32(old->e2fs_algo);
+       new->e2fs_reserved_ngdb =       bswap16(old->e2fs_reserved_ngdb);
+}
+
+void e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
+{
+       int i;
+
+       for (i = 0; i < (size / sizeof(struct ext2_gd)); i++) {
+               new[i].ext2bgd_b_bitmap = bswap32(old[i].ext2bgd_b_bitmap);
+               new[i].ext2bgd_i_bitmap = bswap32(old[i].ext2bgd_i_bitmap);
+               new[i].ext2bgd_i_tables = bswap32(old[i].ext2bgd_i_tables);
+               new[i].ext2bgd_nbfree   = bswap16(old[i].ext2bgd_nbfree);
+               new[i].ext2bgd_nifree   = bswap16(old[i].ext2bgd_nifree);
+               new[i].ext2bgd_ndirs    = bswap16(old[i].ext2bgd_ndirs);
+       }
+}
+
+void e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new)
+{
+
+       new->e2di_mode          =       bswap16(old->e2di_mode);
+       new->e2di_uid           =       bswap16(old->e2di_uid);
+       new->e2di_gid           =       bswap16(old->e2di_gid);
+       new->e2di_nlink         =       bswap16(old->e2di_nlink);
+       new->e2di_size          =       bswap32(old->e2di_size);
+       new->e2di_atime         =       bswap32(old->e2di_atime);
+       new->e2di_ctime         =       bswap32(old->e2di_ctime);
+       new->e2di_mtime         =       bswap32(old->e2di_mtime);
+       new->e2di_dtime         =       bswap32(old->e2di_dtime);
+       new->e2di_nblock        =       bswap32(old->e2di_nblock);
+       new->e2di_flags         =       bswap32(old->e2di_flags);
+       new->e2di_gen           =       bswap32(old->e2di_gen);
+       new->e2di_facl          =       bswap32(old->e2di_facl);
+       new->e2di_dacl          =       bswap32(old->e2di_dacl);
+       new->e2di_faddr         =       bswap32(old->e2di_faddr);
+       memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0],
+           (NDADDR + NIADDR) * sizeof(uint32_t));
+}
+#endif
+
+#ifdef EXT2FS_DEBUG
+void
+dump_sblock(struct m_ext2fs *fs)
+{
+
+       printf("fs->e2fs.e2fs_bcount = %u\n", fs->e2fs.e2fs_bcount);
+       printf("fs->e2fs.e2fs_first_dblock = %u\n", fs->e2fs.e2fs_first_dblock);
+       printf("fs->e2fs.e2fs_log_bsize = %u\n", fs->e2fs.e2fs_log_bsize);
+       printf("fs->e2fs.e2fs_bpg = %u\n", fs->e2fs.e2fs_bpg);
+       printf("fs->e2fs.e2fs_ipg = %u\n", fs->e2fs.e2fs_ipg);
+       printf("fs->e2fs.e2fs_magic = 0x%x\n", fs->e2fs.e2fs_magic);
+       printf("fs->e2fs.e2fs_rev = %u\n", fs->e2fs.e2fs_rev);
+
+       if (fs->e2fs.e2fs_rev == E2FS_REV1) {
+               printf("fs->e2fs.e2fs_first_ino = %u\n",
+                   fs->e2fs.e2fs_first_ino);
+               printf("fs->e2fs.e2fs_inode_size = %u\n",
+                   fs->e2fs.e2fs_inode_size);
+               printf("fs->e2fs.e2fs_features_compat = %u\n",
+                   fs->e2fs.e2fs_features_compat);
+               printf("fs->e2fs.e2fs_features_incompat = %u\n",
+                   fs->e2fs.e2fs_features_incompat);
+               printf("fs->e2fs.e2fs_features_rocompat = %u\n",
+                   fs->e2fs.e2fs_features_rocompat);
+               printf("fs->e2fs.e2fs_reserved_ngdb = %u\n",
+                   fs->e2fs.e2fs_reserved_ngdb);
+       }
+
+       printf("fs->e2fs_bsize = %u\n", fs->e2fs_bsize);
+       printf("fs->e2fs_fsbtodb = %u\n", fs->e2fs_fsbtodb);
+       printf("fs->e2fs_ncg = %u\n", fs->e2fs_ncg);
+       printf("fs->e2fs_ngdb = %u\n", fs->e2fs_ngdb);
+       printf("fs->e2fs_ipb = %u\n", fs->e2fs_ipb);
+       printf("fs->e2fs_itpg = %u\n", fs->e2fs_itpg);
+}
+#endif
diff --git a/sys/lib/libsa/ext2fs.h b/sys/lib/libsa/ext2fs.h
new file mode 100644 (file)
index 0000000..a7add8e
--- /dev/null
@@ -0,0 +1,34 @@
+/* $NetBSD: ext2fs.h,v 1.1 2007/12/01 18:06:22 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ufs.h       8.1 (Berkeley) 6/11/93
+ */
+
+FS_DEF(ext2fs);
diff --git a/sys/lib/libsa/ffsv1.c b/sys/lib/libsa/ffsv1.c
new file mode 100644 (file)
index 0000000..6fb1caa
--- /dev/null
@@ -0,0 +1,20 @@
+/* $NetBSD: ffsv1.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */
+
+#define LIBSA_FFSv1
+
+#define ufs_open       ffsv1_open
+#define ufs_close      ffsv1_close
+#define ufs_read       ffsv1_read
+#define ufs_write      ffsv1_write
+#define ufs_seek       ffsv1_seek
+#define ufs_stat       ffsv1_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define ufs_ls         ffsv1_ls
+#endif
+
+#define ufs_dinode     ufs1_dinode
+#define indp_t         int32_t
+
+#define        FSMOD           "ffs"
+
+#include "ufs.c"
diff --git a/sys/lib/libsa/ffsv2.c b/sys/lib/libsa/ffsv2.c
new file mode 100644 (file)
index 0000000..a5e5585
--- /dev/null
@@ -0,0 +1,20 @@
+/* $NetBSD: ffsv2.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */
+
+#define LIBSA_FFSv2
+
+#define ufs_open       ffsv2_open
+#define ufs_close      ffsv2_close
+#define ufs_read       ffsv2_read
+#define ufs_write      ffsv2_write
+#define ufs_seek       ffsv2_seek
+#define ufs_stat       ffsv2_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define ufs_ls         ffsv2_ls
+#endif
+
+#define ufs_dinode     ufs2_dinode
+#define indp_t         int64_t
+
+#define        FSMOD           "ffs"
+
+#include "ufs.c"
diff --git a/sys/lib/libsa/files.c b/sys/lib/libsa/files.c
new file mode 100644 (file)
index 0000000..ab216b1
--- /dev/null
@@ -0,0 +1,12 @@
+/* $NetBSD: files.c,v 1.1 2002/03/15 13:23:34 simonb Exp $ */
+
+/*
+ *     files.c:
+ *
+ *     libsa file table.  separate from other global variables so that
+ *     all of those don't need to be linked in just to use open, et al.
+ */
+
+#include "stand.h"
+
+struct open_file files[SOPEN_MAX];
diff --git a/sys/lib/libsa/fstat.c b/sys/lib/libsa/fstat.c
new file mode 100644 (file)
index 0000000..0b4fc8b
--- /dev/null
@@ -0,0 +1,58 @@
+/*     $NetBSD: fstat.c,v 1.7 2007/12/02 04:59:25 tsutsui Exp $        */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)stat.c      8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+int
+fstat(int fd, struct stat *sb)
+{
+       struct open_file *f = &files[fd];
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       /* operation not defined on raw devices */
+       if (f->f_flags & F_RAW) {
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+#endif
+
+       errno = FS_STAT(f->f_ops)(f, sb);       /* XXX no point setting errno */
+       return 0;
+}
diff --git a/sys/lib/libsa/getfile.c b/sys/lib/libsa/getfile.c
new file mode 100644 (file)
index 0000000..ef2d1e0
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: getfile.c,v 1.9 2007/11/24 13:20:55 isaki Exp $        */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)getfile.c   8.1 (Berkeley) 6/11/93
+ */
+#include "stand.h"
+
+#define CTRL(x) ((x) & 037)
+
+int
+getfile(char *prompt, int mode)
+{
+       int fd;
+       char buf[100];
+
+       do {
+               printf("%s: ", prompt);
+               gets(buf);
+               if (buf[0] == CTRL('d') && buf[1] == 0)
+                       return -1;
+       } while ((fd = open(buf, mode)) < 0);
+
+       return fd;
+}
diff --git a/sys/lib/libsa/gets.c b/sys/lib/libsa/gets.c
new file mode 100644 (file)
index 0000000..1cda433
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: gets.c,v 1.10 2007/11/24 13:20:55 isaki Exp $  */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)gets.c      8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+void
+gets(char *buf)
+{
+       int c;
+       char *lp;
+
+       for (lp = buf;;) {
+               switch (c = getchar() & 0177) {
+               case '\n':
+               case '\r':
+                       *lp = '\0';
+                       putchar('\n');
+                       return;
+               case '\b':
+               case '\177':
+                       if (lp > buf) {
+                               lp--;
+                               putchar('\b');
+                               putchar(' ');
+                               putchar('\b');
+                       }
+                       break;
+#if HASH_ERASE
+               case '#':
+                       if (lp > buf)
+                               --lp;
+                       break;
+#endif
+               case 'r' & 037: {
+                       char *p;
+
+                       putchar('\n');
+                       for (p = buf; p < lp; ++p)
+                               putchar(*p);
+                       break;
+               }
+#if AT_ERASE
+               case '@':
+#endif
+               case 'u' & 037:
+               case 'w' & 037:
+                       lp = buf;
+                       putchar('\n');
+                       break;
+               default:
+                       *lp++ = c;
+                       putchar(c);
+                       break;
+               }
+       }
+       /*NOTREACHED*/
+}
diff --git a/sys/lib/libsa/globals.c b/sys/lib/libsa/globals.c
new file mode 100644 (file)
index 0000000..c22960a
--- /dev/null
@@ -0,0 +1,27 @@
+/*     $NetBSD: globals.c,v 1.8 2008/11/19 12:36:41 ad Exp $   */
+
+/*
+ *     globals.c:
+ *
+ *     global variables should be separate, so nothing else
+ *     must be included extraneously.
+ */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "net.h"
+
+u_char bcea[6] = BA;                   /* broadcast ethernet address */
+
+char   rootpath[FNAME_SIZE];           /* root mount path */
+char   bootfile[FNAME_SIZE];           /* bootp says to boot this */
+char   hostname[FNAME_SIZE];           /* our hostname */
+char   *fsmod =  "ffs";                /* guessed file system module name */
+char   *fsmod2;                        /* a requisite module */
+struct in_addr myip;                   /* my ip address */
+struct in_addr rootip;                 /* root ip address */
+struct in_addr gateip;                 /* swap ip address */
+n_long netmask = 0xffffff00;           /* subnet or net mask */
diff --git a/sys/lib/libsa/ioctl.c b/sys/lib/libsa/ioctl.c
new file mode 100644 (file)
index 0000000..85b514a
--- /dev/null
@@ -0,0 +1,88 @@
+/*     $NetBSD: ioctl.c,v 1.11 2007/12/02 04:59:25 tsutsui Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ioctl.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+int
+ioctl(int fd, u_long cmd, char *arg)
+{
+#if !defined(LIBSA_NO_FD_CHECKING) || !defined(LIBSA_NO_RAW_ACCESS)
+       struct open_file *f = &files[fd];
+#endif
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       if (f->f_flags & F_RAW) {
+               errno = DEV_IOCTL(f->f_dev)(f, cmd, arg);
+               if (errno)
+                       return -1;
+               return 0;
+       }
+#endif
+       errno = EIO;
+       return -1;
+}
diff --git a/sys/lib/libsa/iodesc.h b/sys/lib/libsa/iodesc.h
new file mode 100644 (file)
index 0000000..884651e
--- /dev/null
@@ -0,0 +1,77 @@
+/*     $NetBSD: iodesc.h,v 1.9 2009/01/17 14:00:36 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 1993 Adam Glass
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __SYS_LIBNETBOOT_IODESC_H
+#define __SYS_LIBNETBOOT_IODESC_H
+
+#ifdef _STANDALONE
+/*
+ * libsa code uses the following types to avoid 64 bit time_t:
+ *
+ * satime_t:
+ *     numbers in seconds returned by the machine dependent getsecs() function
+ *     which are used to measure relative time
+ *
+ * saseconds_t:
+ *     numbers in seconds used to specify timeout to network drivers
+ *
+ */
+typedef unsigned int   satime_t;
+typedef int            saseconds_t;
+#else
+typedef time_t         satime_t;
+typedef time_t         saseconds_t;
+#endif
+
+struct iodesc {
+       struct  in_addr destip;         /* dest. ip addr, net order */
+       struct  in_addr myip;           /* local ip addr, net order */
+       u_short destport;               /* dest. port, net order */
+       u_short myport;                 /* local port, net order */
+       u_long  xid;                    /* transaction identification */
+       u_char  myea[6];                /* my ethernet address */
+       void    *io_netif;
+};
+
+struct iodesc  *socktodesc(int);
+ssize_t                netif_get(struct iodesc *, void *, size_t, saseconds_t);
+ssize_t                netif_put(struct iodesc *, void *, size_t);
+
+#endif /* __SYS_LIBNETBOOT_IODESC_H */
diff --git a/sys/lib/libsa/ip.c b/sys/lib/libsa/ip.c
new file mode 100644 (file)
index 0000000..50aee4d
--- /dev/null
@@ -0,0 +1,190 @@
+/* $NetBSD: ip.c,v 1.2 2011/05/13 23:35:09 nakayama Exp $ */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * Copyright (c) 2010 Zoltan Arnold NAGY
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "net.h"
+
+/*
+ * sends an IP packet, if it's alredy constructed
+*/
+static ssize_t
+_sendip(struct iodesc * d, struct ip * ip, size_t len)
+{
+       u_char *ea;
+
+       if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 ||
+           netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) {
+               ea = arpwhohas(d, ip->ip_dst);
+       } else {
+               ea = arpwhohas(d, gateip);
+       }
+
+       return sendether(d, ip, len, ea, ETHERTYPE_IP);
+}
+
+/*
+ * fills out the IP header
+ * Caller must leave room for ethernet, ip and udp headers in front!
+*/
+ssize_t
+sendip(struct iodesc * d, void *pkt, size_t len, u_int8_t proto)
+{
+       ssize_t cc;
+       struct ip *ip;
+
+       ip = (struct ip *) pkt - 1;
+       len += sizeof(*ip);
+
+       (void) memset(ip, 0, sizeof(*ip));
+
+       ip->ip_v = IPVERSION;
+       ip->ip_hl = sizeof(*ip) >> 2;
+       ip->ip_len = htons(len);
+       ip->ip_p = proto;
+       ip->ip_ttl = IPDEFTTL;
+       ip->ip_src = d->myip;
+       ip->ip_dst = d->destip;
+       ip->ip_sum = ip_cksum(ip, sizeof(*ip));
+
+       cc = _sendip(d, ip, len);
+
+       if (cc == -1)
+               return -1;
+       if ((size_t) cc != len)
+               panic("sendip: bad write (%zd != %zu)", cc, len);
+       return (cc - (sizeof(*ip)));
+}
+
+/*
+ * reads an IP packet
+ * WARNING: the old version stripped the IP options, if there were
+ * any. Because we have absolutely no idea if the upper layer needs
+ * these or not, it's best to leave them there.
+ *
+ * The size returned is the size indicated in the header.
+ */
+ssize_t
+readip(struct iodesc * d, void *pkt, size_t len, time_t tleft, u_int8_t proto)
+{
+       ssize_t n;
+       size_t hlen;
+       struct ip *ip;
+       u_int16_t etype;
+
+       ip = (struct ip *) pkt - 1;
+
+       n = readether(d, ip, len + sizeof(*ip), tleft, &etype);
+       if (n == -1 || (size_t) n < sizeof(*ip))
+               return -1;
+
+       if (etype == ETHERTYPE_ARP) {
+               struct arphdr *ah = (void *) ip;
+               if (ah->ar_op == htons(ARPOP_REQUEST)) {
+                       /* Send ARP reply */
+                       arp_reply(d, ah);
+               }
+               return -1;
+       }
+
+       if (etype != ETHERTYPE_IP) {
+#ifdef NET_DEBUG
+               if (debug)
+                       printf("readip: not IP. ether_type=%x\n", etype);
+#endif
+               return -1;
+       }
+
+       /* Check ip header */
+       if (ip->ip_v != IPVERSION ||
+           ip->ip_p != proto) { /* half char */
+#ifdef NET_DEBUG
+               if (debug) {
+                       printf("readip: wrong IP version or wrong proto "
+                               "ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p);
+               }
+#endif
+               return -1;
+       }
+
+       hlen = ip->ip_hl << 2;
+       if (hlen < sizeof(*ip) || ip_cksum(ip, hlen) != 0) {
+#ifdef NET_DEBUG
+               if (debug)
+                       printf("readip: short hdr or bad cksum.\n");
+#endif
+               return -1;
+       }
+       if (n < ntohs(ip->ip_len)) {
+#ifdef NET_DEBUG
+               if (debug)
+                       printf("readip: bad length %d < %d.\n",
+                              (int) n, ntohs(ip->ip_len));
+#endif
+               return -1;
+       }
+       if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) {
+#ifdef NET_DEBUG
+               if (debug) {
+                       printf("readip: bad saddr %s != ", inet_ntoa(d->myip));
+                       printf("%s\n", inet_ntoa(ip->ip_dst));
+               }
+#endif
+               return -1;
+       }
+       return (ntohs(ip->ip_len) - 20);
+}
diff --git a/sys/lib/libsa/ip_cksum.c b/sys/lib/libsa/ip_cksum.c
new file mode 100644 (file)
index 0000000..429416b
--- /dev/null
@@ -0,0 +1,106 @@
+/*     $NetBSD: ip_cksum.c,v 1.2 2006/01/25 13:46:09 christos Exp $    */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: in_cksum.c,v 1.1 92/09/11 01:15:55 leres Exp  (LBL)
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <machine/endian.h>
+
+#include "stand.h"
+#include "net.h"
+
+/*
+ * Checksum routine for Internet Protocol family headers.
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ * In particular, it should not be this one.
+ */
+int
+ip_cksum(const void *p, size_t llen)
+{
+       int sum = 0, oddbyte = 0, v = 0, len = (int)llen;
+       const u_char *cp = p;
+
+       /* we assume < 2^16 bytes being summed */
+       while (len > 0) {
+               if (oddbyte) {
+                       sum += v + *cp++;
+                       len--;
+               }
+               if (((long)cp & 1) == 0) {
+                       while ((len -= 2) >= 0) {
+                               sum += *(const u_short *)cp;
+                               cp += 2;
+                       }
+               } else {
+                       while ((len -= 2) >= 0) {
+#if BYTE_ORDER == BIG_ENDIAN
+                               sum += *cp++ << 8;
+                               sum += *cp++;
+#else
+                               sum += *cp++;
+                               sum += *cp++ << 8;
+#endif
+                       }
+               }
+               if ((oddbyte = len & 1) != 0)
+#if BYTE_ORDER == BIG_ENDIAN
+                       v = *cp << 8;
+#else
+                       v = *cp;
+#endif
+       }
+       if (oddbyte)
+               sum += v;
+       sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
+       sum += sum >> 16;               /* add potential last carry */
+       return (0xffff & ~sum);
+}
diff --git a/sys/lib/libsa/lfs.h b/sys/lib/libsa/lfs.h
new file mode 100644 (file)
index 0000000..3698afb
--- /dev/null
@@ -0,0 +1,35 @@
+/* $NetBSD: lfs.h,v 1.5 2005/12/11 12:24:46 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ufs.h       8.1 (Berkeley) 6/11/93
+ */
+
+FS_DEF(lfsv1);
+FS_DEF(lfsv2);
diff --git a/sys/lib/libsa/lfsv1.c b/sys/lib/libsa/lfsv1.c
new file mode 100644 (file)
index 0000000..7dfc107
--- /dev/null
@@ -0,0 +1,25 @@
+/* $NetBSD: lfsv1.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */
+
+#define        LIBSA_LFS
+#define        REQUIRED_LFS_VERSION    1
+
+#define        ufs_open                lfsv1_open
+#define        ufs_close               lfsv1_close
+#define        ufs_read                lfsv1_read
+#define        ufs_write               lfsv1_write
+#define        ufs_seek                lfsv1_seek
+#define        ufs_stat                lfsv1_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define        ufs_ls                  lfsv1_ls
+#endif
+
+#define        fs_bsize                lfs_ibsize
+#define        IFILE_Vx                IFILE_V1
+
+#define        FSBTODB(fs, daddr)      (daddr)         /* LFSv1 uses sectors for addresses */
+#define        INOPBx(fs) INOPB(fs)
+
+#define        FSMOD                   "lfs"
+#define        FSMOD2                  "ffs"
+
+#include "lib/libsa/ufs.c"
diff --git a/sys/lib/libsa/lfsv2.c b/sys/lib/libsa/lfsv2.c
new file mode 100644 (file)
index 0000000..498a938
--- /dev/null
@@ -0,0 +1,28 @@
+/* $NetBSD: lfsv2.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */
+
+#define        LIBSA_LFS
+#define        REQUIRED_LFS_VERSION    2
+
+#define        ufs_open                lfsv2_open
+#define        ufs_close               lfsv2_close
+#define        ufs_read                lfsv2_read
+#define        ufs_write               lfsv2_write
+#define        ufs_seek                lfsv2_seek
+#define        ufs_stat                lfsv2_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define        ufs_ls                  lfsv2_ls
+#endif
+
+#define        fs_bsize                lfs_bsize
+#define        IFILE_Vx                IFILE
+
+#ifdef LFS_IFILE_FRAG_ADDRESSING       /* XXX see sys/ufs/lfs/ -- not tested */
+#define        INOPBx(fs) INOPF(fs)
+#else
+#define        INOPBx(fs) INOPB(fs)
+#endif
+
+#define        FSMOD                   "lfs"
+#define        FSMOD2                  "ffs"
+
+#include "lib/libsa/ufs.c"
diff --git a/sys/lib/libsa/loadfile.c b/sys/lib/libsa/loadfile.c
new file mode 100644 (file)
index 0000000..b4fce23
--- /dev/null
@@ -0,0 +1,194 @@
+/* $NetBSD: loadfile.c,v 1.30 2008/05/20 16:04:08 ad Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center and by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)boot.c      8.1 (Berkeley) 6/10/93
+ */
+
+#ifdef _STANDALONE
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/exec.h>
+
+#include "loadfile.h"
+
+uint32_t       netbsd_version;
+u_int          netbsd_elf_class;
+
+/*
+ * Open 'filename', read in program and return the opened file
+ * descriptor if ok, or -1 on error.
+ * Fill in marks
+ */
+int
+loadfile(const char *fname, u_long *marks, int flags)
+{
+       int fd, error;
+
+       /* Open the file. */
+       if ((fd = open(fname, 0)) < 0) {
+               WARN(("open %s", fname ? fname : "<default>"));
+               return -1;
+       }
+
+       /* Load it; save the value of errno across the close() call */
+       if ((error = fdloadfile(fd, marks, flags)) != 0) {
+               (void)close(fd);
+               errno = error;
+               return -1;
+       }
+
+       return fd;
+}
+
+/*
+ * Read in program from the given file descriptor.
+ * Return error code (0 on success).
+ * Fill in marks.
+ */
+int
+fdloadfile(int fd, u_long *marks, int flags)
+{
+       union {
+#ifdef BOOT_ECOFF
+               struct ecoff_exechdr coff;
+#endif
+#ifdef BOOT_ELF32
+               Elf32_Ehdr elf32;
+#endif
+#ifdef BOOT_ELF64
+               Elf64_Ehdr elf64;
+#endif
+#ifdef BOOT_AOUT
+               struct exec aout;
+#endif
+       } hdr;
+       ssize_t nr;
+       int rval;
+
+       /* Read the exec header. */
+       if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
+               goto err;
+       nr = read(fd, &hdr, sizeof(hdr));
+       if (nr == -1) {
+               WARN(("read header failed"));
+               goto err;
+       }
+       if (nr != sizeof(hdr)) {
+               WARN(("read header short"));
+               errno = EFTYPE;
+               goto err;
+       }
+
+#ifdef BOOT_ECOFF
+       if (!ECOFF_BADMAG(&hdr.coff)) {
+               rval = loadfile_coff(fd, &hdr.coff, marks, flags);
+       } else
+#endif
+#ifdef BOOT_ELF32
+       if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
+           hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
+               netbsd_elf_class = ELFCLASS32;
+               rval = loadfile_elf32(fd, &hdr.elf32, marks, flags);
+       } else
+#endif
+#ifdef BOOT_ELF64
+       if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
+           hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
+               netbsd_elf_class = ELFCLASS64;
+               rval = loadfile_elf64(fd, &hdr.elf64, marks, flags);
+       } else
+#endif
+#ifdef BOOT_AOUT
+       if (OKMAGIC(N_GETMAGIC(hdr.aout))
+#ifndef NO_MID_CHECK
+           && N_GETMID(hdr.aout) == MID_MACHINE
+#endif
+           ) {
+               rval = loadfile_aout(fd, &hdr.aout, marks, flags);
+       } else
+#endif
+       {
+               rval = 1;
+               errno = EFTYPE;
+       }
+
+       if (rval == 0) {
+               if ((flags & LOAD_ALL) != 0)
+                       PROGRESS(("=0x%lx\n",
+                                 marks[MARK_END] - marks[MARK_START]));
+               return 0;
+       }
+err:
+       return errno;
+}
diff --git a/sys/lib/libsa/loadfile.h b/sys/lib/libsa/loadfile.h
new file mode 100644 (file)
index 0000000..44af423
--- /dev/null
@@ -0,0 +1,94 @@
+/*     $NetBSD: loadfile.h,v 1.12 2010/08/25 16:30:01 christos Exp $    */
+
+/*-
+ * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Array indices in the u_long position array
+ */
+#define MARK_START     0
+#define MARK_ENTRY     1
+#define        MARK_DATA       2
+#define        MARK_NSYM       3
+#define MARK_SYM       4
+#define        MARK_END        5
+#define        MARK_MAX        6
+
+/*
+ * Bit flags for sections to load
+ */
+#define        LOAD_TEXT       0x0001
+#define        LOAD_TEXTA      0x0002
+#define        LOAD_DATA       0x0004
+#define        LOAD_BSS        0x0008
+#define        LOAD_SYM        0x0010
+#define        LOAD_HDR        0x0020
+#define LOAD_NOTE      0x0040
+#define LOAD_ALL       0x007f
+#define LOAD_MINIMAL   0x002f
+#define LOAD_BACKWARDS 0x0050
+
+#define        COUNT_TEXT      0x0100
+#define        COUNT_TEXTA     0x0200
+#define        COUNT_DATA      0x0400
+#define        COUNT_BSS       0x0800
+#define        COUNT_SYM       0x1000
+#define        COUNT_HDR       0x2000
+#define COUNT_ALL      0x3f00
+
+int    loadfile(const char *, u_long *, int);
+int    fdloadfile(int fd, u_long *, int);
+
+#ifndef MACHINE_LOADFILE_MACHDEP
+#define MACHINE_LOADFILE_MACHDEP "machine/loadfile_machdep.h"
+#endif
+#include MACHINE_LOADFILE_MACHDEP
+
+#ifdef BOOT_ECOFF
+#include <sys/exec_ecoff.h>
+int    loadfile_coff(int, struct ecoff_exechdr *, u_long *, int);
+#endif
+
+#if defined(BOOT_ELF32) || defined(BOOT_ELF64)
+#include <sys/exec_elf.h>
+#ifdef BOOT_ELF32
+int    loadfile_elf32(int, Elf32_Ehdr *, u_long *, int);
+#endif
+#ifdef BOOT_ELF64
+int    loadfile_elf64(int, Elf64_Ehdr *, u_long *, int);
+#endif
+#endif /* BOOT_ELF32 || BOOT_ELF64 */
+
+#ifdef BOOT_AOUT
+#include <sys/exec_aout.h>
+int    loadfile_aout(int, struct exec *, u_long *, int);
+#endif
+
+extern uint32_t        netbsd_version;
+extern u_int netbsd_elf_class;
diff --git a/sys/lib/libsa/loadfile_aout.c b/sys/lib/libsa/loadfile_aout.c
new file mode 100644 (file)
index 0000000..eb395e8
--- /dev/null
@@ -0,0 +1,304 @@
+/* $NetBSD: loadfile_aout.c,v 1.14 2009/08/16 13:26:16 matt Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center and by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)boot.c      8.1 (Berkeley) 6/10/93
+ */
+
+#ifdef _STANDALONE
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/exec_aout.h>
+
+#include "loadfile.h"
+
+#ifdef BOOT_AOUT
+
+int
+loadfile_aout(int fd, struct exec *x, u_long *marks, int flags)
+{
+       u_long entry = x->a_entry;
+       paddr_t aoutp = 0;
+       paddr_t minp, maxp;
+       int cc;
+       paddr_t offset = marks[MARK_START];
+       u_long magic = N_GETMAGIC(*x);
+       int sub;
+       ssize_t nr;
+
+       /* some ports dont use the offset */
+       offset = offset;
+
+       /* In OMAGIC and NMAGIC, exec header isn't part of text segment */
+       if (magic == OMAGIC || magic == NMAGIC)
+               sub = 0;
+       else
+               sub = sizeof(*x);
+
+       minp = maxp = ALIGNENTRY(entry);
+
+       if (lseek(fd, sizeof(*x), SEEK_SET) == -1)  {
+               WARN(("lseek text"));
+               return 1;
+       }
+
+       /*
+        * Leave a copy of the exec header before the text.
+        * The kernel may use this to verify that the
+        * symbols were loaded by this boot program.
+        */
+       if (magic == OMAGIC || magic == NMAGIC) {
+               if (flags & LOAD_HDR && maxp >= sizeof(*x))
+                       BCOPY(x, maxp - sizeof(*x), sizeof(*x));
+       }
+       else {
+               if (flags & LOAD_HDR)
+                       BCOPY(x, maxp, sizeof(*x));
+               if (flags & (LOAD_HDR|COUNT_HDR))
+                       maxp += sizeof(*x);
+       }
+
+       /*
+        * Read in the text segment.
+        */
+       if (flags & LOAD_TEXT) {
+               PROGRESS(("%ld", x->a_text));
+
+               nr = READ(fd, maxp, x->a_text - sub);
+               if (nr == -1) {
+                       WARN(("read text"));
+                       return 1;
+               }
+               if (nr != (ssize_t)(x->a_text - sub)) {
+                       errno = EIO;
+                       WARN(("read text"));
+                       return 1;
+               }
+       } else {
+               if (lseek(fd, x->a_text - sub, SEEK_CUR) == -1) {
+                       WARN(("seek text"));
+                       return 1;
+               }
+       }
+       if (flags & (LOAD_TEXT|COUNT_TEXT))
+               maxp += x->a_text - sub;
+
+       /*
+        * Provide alignment if required
+        */
+       if (magic == ZMAGIC || magic == NMAGIC) {
+               int size = -(unsigned int)maxp & (AOUT_LDPGSZ - 1);
+
+               if (flags & LOAD_TEXTA) {
+                       PROGRESS(("/%d", size));
+                       BZERO(maxp, size);
+               }
+
+               if (flags & (LOAD_TEXTA|COUNT_TEXTA))
+                       maxp += size;
+       }
+
+       /*
+        * Read in the data segment.
+        */
+       if (flags & LOAD_DATA) {
+               PROGRESS(("+%ld", x->a_data));
+
+               marks[MARK_DATA] = LOADADDR(maxp);
+               nr = READ(fd, maxp, x->a_data);
+               if (nr == -1) {
+                       WARN(("read data"));
+                       return 1;
+               }
+               if (nr != (ssize_t)x->a_data) {
+                       errno = EIO;
+                       WARN(("read data"));
+                       return 1;
+               }
+       }
+       else {
+               if (lseek(fd, x->a_data, SEEK_CUR) == -1) {
+                       WARN(("seek data"));
+                       return 1;
+               }
+       }
+       if (flags & (LOAD_DATA|COUNT_DATA))
+               maxp += x->a_data;
+
+       /*
+        * Zero out the BSS section.
+        * (Kernel doesn't care, but do it anyway.)
+        */
+       if (flags & LOAD_BSS) {
+               PROGRESS(("+%ld", x->a_bss));
+
+               BZERO(maxp, x->a_bss);
+       }
+
+       if (flags & (LOAD_BSS|COUNT_BSS))
+               maxp += x->a_bss;
+
+       /*
+        * Read in the symbol table and strings.
+        * (Always set the symtab size word.)
+        */
+       if (flags & LOAD_SYM)
+               BCOPY(&x->a_syms, maxp, sizeof(x->a_syms));
+
+       if (flags & (LOAD_SYM|COUNT_SYM)) {
+               maxp += sizeof(x->a_syms);
+               aoutp = maxp;
+       }
+
+       if (x->a_syms > 0) {
+               /* Symbol table and string table length word. */
+
+               if (flags & LOAD_SYM) {
+                       PROGRESS(("+[%ld", x->a_syms));
+
+                       nr = READ(fd, maxp, x->a_syms);
+                       if (nr == -1) {
+                               WARN(("read symbols"));
+                               return 1;
+                       }
+                       if (nr != (ssize_t)x->a_syms) {
+                               errno = EIO;
+                               WARN(("read symbols"));
+                               return 1;
+                       }
+               } else  {
+                       if (lseek(fd, x->a_syms, SEEK_CUR) == -1) {
+                               WARN(("seek symbols"));
+                               return 1;
+                       }
+               }
+               if (flags & (LOAD_SYM|COUNT_SYM))
+                       maxp += x->a_syms;
+
+               nr = read(fd, &cc, sizeof(cc));
+               if (nr == -1) {
+                       WARN(("read string table"));
+                       return 1;
+               }
+               if (nr != sizeof(cc)) {
+                       errno = EIO;
+                       WARN(("read string table"));
+                       return 1;
+               }
+
+               if (flags & LOAD_SYM) {
+                       BCOPY(&cc, maxp, sizeof(cc));
+
+                       /* String table. Length word includes itself. */
+
+                       PROGRESS(("+%d]", cc));
+               }
+               if (flags & (LOAD_SYM|COUNT_SYM))
+                       maxp += sizeof(cc);
+
+               cc -= sizeof(int);
+               if (cc <= 0) {
+                       WARN(("symbol table too short"));
+                       return 1;
+               }
+
+               if (flags & LOAD_SYM) {
+                       nr = READ(fd, maxp, cc);
+                       if (nr == -1) {
+                               WARN(("read strings"));
+                               return 1;
+                       }
+                       if (nr != cc) {
+                               errno = EIO;
+                               WARN(("read strings"));
+                               return 1;
+                       }
+               } else {
+                       if (lseek(fd, cc, SEEK_CUR) == -1) {
+                               WARN(("seek strings"));
+                               return 1;
+                       }
+               }
+               if (flags & (LOAD_SYM|COUNT_SYM))
+                       maxp += cc;
+       }
+
+       marks[MARK_START] = LOADADDR(minp);
+       marks[MARK_ENTRY] = LOADADDR(entry);
+       marks[MARK_NSYM] = x->a_syms;
+       marks[MARK_SYM] = LOADADDR(aoutp);
+       marks[MARK_END] = LOADADDR(maxp);
+       return 0;
+}
+
+#endif /* BOOT_AOUT */
diff --git a/sys/lib/libsa/loadfile_ecoff.c b/sys/lib/libsa/loadfile_ecoff.c
new file mode 100644 (file)
index 0000000..73155d7
--- /dev/null
@@ -0,0 +1,147 @@
+/* $NetBSD: loadfile_ecoff.c,v 1.12 2008/04/28 20:24:06 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center and by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef _STANDALONE
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/exec.h>
+
+#include "loadfile.h"
+
+#ifdef BOOT_ECOFF
+
+int
+loadfile_coff(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags)
+{
+       paddr_t offset = marks[MARK_START];
+       paddr_t minp = ~0, maxp = 0, pos;
+       ssize_t nr;
+
+       /* some ports dont use the offset */
+       offset = offset;
+
+       /* Read in text. */
+       if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1)  {
+               WARN(("lseek text"));
+               return 1;
+       }
+
+       if (coff->a.tsize != 0) {
+               if (flags & LOAD_TEXT) {
+                       PROGRESS(("%lu", coff->a.tsize));
+                       nr = READ(fd, coff->a.text_start, coff->a.tsize);
+                       if (nr == -1) {
+                               return 1;
+                       }
+                       if (nr != coff->a.tsize) {
+                               errno = EIO;
+                               return 1;
+                       }
+               }
+               else {
+                       if (lseek(fd, coff->a.tsize, SEEK_CUR) == -1) {
+                               WARN(("read text"));
+                               return 1;
+                       }
+               }
+               if (flags & (COUNT_TEXT|LOAD_TEXT)) {
+                       pos = coff->a.text_start;
+                       if (minp > pos)
+                               minp = pos;
+                       pos += coff->a.tsize;
+                       if (maxp < pos)
+                               maxp = pos;
+               }
+       }
+
+       /* Read in data. */
+       if (coff->a.dsize != 0) {
+               if (flags & LOAD_DATA) {
+                       PROGRESS(("+%lu", coff->a.dsize));
+                       nr = READ(fd, coff->a.data_start, coff->a.dsize);
+                       if (nr == -1) {
+                               WARN(("read data"));
+                               return 1;
+                       }
+                       if (nr != coff->a.dsize) {
+                               errno = EIO;
+                               WARN(("read data"));
+                               return 1;
+                       }
+               }
+               if (flags & (COUNT_DATA|LOAD_DATA)) {
+                       pos = coff->a.data_start;
+                       if (minp > pos)
+                               minp = pos;
+                       pos += coff->a.dsize;
+                       if (maxp < pos)
+                               maxp = pos;
+               }
+       }
+
+       /* Zero out bss. */
+       if (coff->a.bsize != 0) {
+               if (flags & LOAD_BSS) {
+                       PROGRESS(("+%lu", coff->a.bsize));
+                       BZERO(coff->a.bss_start, coff->a.bsize);
+               }
+               if (flags & (COUNT_BSS|LOAD_BSS)) {
+                       pos = coff->a.bss_start;
+                       if (minp > pos)
+                               minp = pos;
+                       pos = coff->a.bsize;
+                       if (maxp < pos)
+                               maxp = pos;
+               }
+       }
+
+       marks[MARK_START] = LOADADDR(minp);
+       marks[MARK_ENTRY] = LOADADDR(coff->a.entry);
+       marks[MARK_NSYM] = 1;   /* XXX: Kernel needs >= 0 */
+       marks[MARK_SYM] = LOADADDR(maxp);
+       marks[MARK_END] = LOADADDR(maxp);
+       marks[MARK_DATA] = LOADADDR(coff->a.data_start);
+       return 0;
+}
+
+#endif /* BOOT_ECOFF */
diff --git a/sys/lib/libsa/loadfile_elf32.c b/sys/lib/libsa/loadfile_elf32.c
new file mode 100644 (file)
index 0000000..1418e8f
--- /dev/null
@@ -0,0 +1,625 @@
+/* $NetBSD: loadfile_elf32.c,v 1.29 2011/02/17 21:15:31 christos Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center and by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* If not included by exec_elf64.c, ELFSIZE won't be defined. */
+#ifndef ELFSIZE
+#define        ELFSIZE 32
+#endif
+
+#ifdef _STANDALONE
+#include <lib/libsa/stand.h>
+#include <lib/libkern/libkern.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/exec.h>
+
+#include "loadfile.h"
+
+#if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
+    ((ELFSIZE == 64) && defined(BOOT_ELF64))
+
+#define        ELFROUND        (ELFSIZE / 8)
+
+#ifndef _STANDALONE
+#include "byteorder.h"
+
+/*
+ * Byte swapping may be necessary in the non-_STANDLONE case because
+ * we may be built with a host compiler.
+ */
+#define        E16(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_htole16(f) : sa_htobe16(f)
+#define        E32(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_htole32(f) : sa_htobe32(f)
+#define        E64(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_htole64(f) : sa_htobe64(f)
+
+#define        I16(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_le16toh(f) : sa_be16toh(f)
+#define        I32(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_le32toh(f) : sa_be32toh(f)
+#define        I64(f)                                                          \
+       f = (bo == ELFDATA2LSB) ? sa_le64toh(f) : sa_be64toh(f)
+
+static void
+internalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
+{
+
+#if ELFSIZE == 32
+       I16(ehdr->e_type);
+       I16(ehdr->e_machine);
+       I32(ehdr->e_version);
+       I32(ehdr->e_entry);
+       I32(ehdr->e_phoff);
+       I32(ehdr->e_shoff);
+       I32(ehdr->e_flags);
+       I16(ehdr->e_ehsize);
+       I16(ehdr->e_phentsize);
+       I16(ehdr->e_phnum);
+       I16(ehdr->e_shentsize);
+       I16(ehdr->e_shnum);
+       I16(ehdr->e_shstrndx);
+#elif ELFSIZE == 64
+       I16(ehdr->e_type);
+       I16(ehdr->e_machine);
+       I32(ehdr->e_version);
+       I64(ehdr->e_entry);
+       I64(ehdr->e_phoff);
+       I64(ehdr->e_shoff);
+       I32(ehdr->e_flags);
+       I16(ehdr->e_ehsize);
+       I16(ehdr->e_phentsize);
+       I16(ehdr->e_phnum);
+       I16(ehdr->e_shentsize);
+       I16(ehdr->e_shnum);
+       I16(ehdr->e_shstrndx);
+#else
+#error ELFSIZE is not 32 or 64
+#endif
+}
+
+static void
+externalize_ehdr(Elf_Byte bo, Elf_Ehdr *ehdr)
+{
+
+#if ELFSIZE == 32
+       E16(ehdr->e_type);
+       E16(ehdr->e_machine);
+       E32(ehdr->e_version);
+       E32(ehdr->e_entry);
+       E32(ehdr->e_phoff);
+       E32(ehdr->e_shoff);
+       E32(ehdr->e_flags);
+       E16(ehdr->e_ehsize);
+       E16(ehdr->e_phentsize);
+       E16(ehdr->e_phnum);
+       E16(ehdr->e_shentsize);
+       E16(ehdr->e_shnum);
+       E16(ehdr->e_shstrndx);
+#elif ELFSIZE == 64
+       E16(ehdr->e_type);
+       E16(ehdr->e_machine);
+       E32(ehdr->e_version);
+       E64(ehdr->e_entry);
+       E64(ehdr->e_phoff);
+       E64(ehdr->e_shoff);
+       E32(ehdr->e_flags);
+       E16(ehdr->e_ehsize);
+       E16(ehdr->e_phentsize);
+       E16(ehdr->e_phnum);
+       E16(ehdr->e_shentsize);
+       E16(ehdr->e_shnum);
+       E16(ehdr->e_shstrndx);
+#else
+#error ELFSIZE is not 32 or 64
+#endif
+}
+
+static void
+internalize_phdr(Elf_Byte bo, Elf_Phdr *phdr)
+{
+
+#if ELFSIZE == 32
+       I32(phdr->p_type);
+       I32(phdr->p_offset);
+       I32(phdr->p_vaddr);
+       I32(phdr->p_paddr);
+       I32(phdr->p_filesz);
+       I32(phdr->p_memsz);
+       I32(phdr->p_flags);
+       I32(phdr->p_align);
+#elif ELFSIZE == 64
+       I32(phdr->p_type);
+       I32(phdr->p_offset);
+       I64(phdr->p_vaddr);
+       I64(phdr->p_paddr);
+       I64(phdr->p_filesz);
+       I64(phdr->p_memsz);
+       I64(phdr->p_flags);
+       I64(phdr->p_align);
+#else
+#error ELFSIZE is not 32 or 64
+#endif
+}
+
+static void
+internalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
+{
+
+#if ELFSIZE == 32
+       I32(shdr->sh_name);
+       I32(shdr->sh_type);
+       I32(shdr->sh_flags);
+       I32(shdr->sh_addr);
+       I32(shdr->sh_offset);
+       I32(shdr->sh_size);
+       I32(shdr->sh_link);
+       I32(shdr->sh_info);
+       I32(shdr->sh_addralign);
+       I32(shdr->sh_entsize);
+#elif ELFSIZE == 64
+       I32(shdr->sh_name);
+       I32(shdr->sh_type);
+       I64(shdr->sh_flags);
+       I64(shdr->sh_addr);
+       I64(shdr->sh_offset);
+       I64(shdr->sh_size);
+       I32(shdr->sh_link);
+       I32(shdr->sh_info);
+       I64(shdr->sh_addralign);
+       I64(shdr->sh_entsize);
+#else
+#error ELFSIZE is not 32 or 64
+#endif
+}
+
+static void
+externalize_shdr(Elf_Byte bo, Elf_Shdr *shdr)
+{
+
+#if ELFSIZE == 32
+       E32(shdr->sh_name);
+       E32(shdr->sh_type);
+       E32(shdr->sh_flags);
+       E32(shdr->sh_addr);
+       E32(shdr->sh_offset);
+       E32(shdr->sh_size);
+       E32(shdr->sh_link);
+       E32(shdr->sh_info);
+       E32(shdr->sh_addralign);
+       E32(shdr->sh_entsize);
+#elif ELFSIZE == 64
+       E32(shdr->sh_name);
+       E32(shdr->sh_type);
+       E64(shdr->sh_flags);
+       E64(shdr->sh_addr);
+       E64(shdr->sh_offset);
+       E64(shdr->sh_size);
+       E32(shdr->sh_link);
+       E32(shdr->sh_info);
+       E64(shdr->sh_addralign);
+       E64(shdr->sh_entsize);
+#else
+#error ELFSIZE is not 32 or 64
+#endif
+}
+#else /* _STANDALONE */
+/*
+ * Byte swapping is never necessary in the _STANDALONE case because
+ * we are being built with the target compiler.
+ */
+#define        internalize_ehdr(bo, ehdr)      /* nothing */
+#define        externalize_ehdr(bo, ehdr)      /* nothing */
+
+#define        internalize_phdr(bo, phdr)      /* nothing */
+
+#define        internalize_shdr(bo, shdr)      /* nothing */
+#define        externalize_shdr(bo, shdr)      /* nothing */
+#endif /* _STANDALONE */
+
+int
+ELFNAMEEND(loadfile)(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
+{
+       Elf_Shdr *shp;
+       Elf_Phdr *phdr;
+       int i, j;
+       ssize_t sz;
+       int first;
+       Elf_Addr shpp;
+       Elf_Addr minp = ~0, maxp = 0, pos = 0, elfp = 0;
+       u_long offset = marks[MARK_START];
+       ssize_t nr;
+       struct __packed {
+               Elf_Nhdr        nh;
+               uint8_t         name[ELF_NOTE_NETBSD_NAMESZ + 1];
+               uint8_t         desc[ELF_NOTE_NETBSD_DESCSZ];
+       } note;
+       char *shstr = NULL;
+       int boot_load_ctf = 1;
+
+       /* some ports dont use the offset */
+       (void)&offset;
+
+       internalize_ehdr(elf->e_ident[EI_DATA], elf);
+
+       sz = elf->e_phnum * sizeof(Elf_Phdr);
+       phdr = ALLOC(sz);
+
+       if (lseek(fd, elf->e_phoff, SEEK_SET) == -1)  {
+               WARN(("lseek phdr"));
+               goto freephdr;
+       }
+       nr = read(fd, phdr, sz);
+       if (nr == -1) {
+               WARN(("read program headers"));
+               goto freephdr;
+       }
+       if (nr != sz) {
+               errno = EIO;
+               WARN(("read program headers"));
+               goto freephdr;
+       }
+
+       for (first = 1, i = 0; i < elf->e_phnum; i++) {
+               internalize_phdr(elf->e_ident[EI_DATA], &phdr[i]);
+
+#ifndef MD_LOADSEG /* Allow processor ABI specific segment loads */
+#define MD_LOADSEG(a) /*CONSTCOND*/0
+#endif
+               if (MD_LOADSEG(&phdr[i]))
+                       goto loadseg;
+
+               if (phdr[i].p_type != PT_LOAD ||
+                   (phdr[i].p_flags & (PF_W|PF_X)) == 0)
+                       continue;
+
+#define IS_TEXT(p)     (p.p_flags & PF_X)
+#define IS_DATA(p)     (p.p_flags & PF_W)
+#define IS_BSS(p)      (p.p_filesz < p.p_memsz)
+               /*
+                * XXX: Assume first address is lowest
+                */
+               if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
+                   (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
+
+               loadseg:
+                       if (marks[MARK_DATA] == 0 && IS_DATA(phdr[i]))
+                               marks[MARK_DATA] = LOADADDR(phdr[i].p_vaddr);
+
+                       /* Read in segment. */
+                       PROGRESS(("%s%lu", first ? "" : "+",
+                           (u_long)phdr[i].p_filesz));
+
+                       if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1)  {
+                               WARN(("lseek text"));
+                               goto freephdr;
+                       }
+                       nr = READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz);
+                       if (nr == -1) {
+                               WARN(("read text error"));
+                               goto freephdr;
+                       }
+                       if (nr != (ssize_t)phdr[i].p_filesz) {
+                               errno = EIO;
+                               WARN(("read text"));
+                               goto freephdr;
+                       }
+                       first = 0;
+
+               }
+               if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
+                   (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) {
+                       pos = phdr[i].p_vaddr;
+                       if (minp > pos)
+                               minp = pos;
+                       pos += phdr[i].p_filesz;
+                       if (maxp < pos)
+                               maxp = pos;
+               }
+
+               /* Zero out bss. */
+               if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
+                       PROGRESS(("+%lu",
+                           (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
+                       BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
+                           phdr[i].p_memsz - phdr[i].p_filesz);
+               }
+               if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
+                       pos += phdr[i].p_memsz - phdr[i].p_filesz;
+                       if (maxp < pos)
+                               maxp = pos;
+               }
+       }
+       DEALLOC(phdr, sz);
+
+       /*
+        * Copy the ELF and section headers.
+        */
+       maxp = roundup(maxp, ELFROUND);
+       if (flags & (LOAD_HDR|COUNT_HDR)) {
+               elfp = maxp;
+               maxp += sizeof(Elf_Ehdr);
+       }
+
+       if (flags & (LOAD_SYM|COUNT_SYM)) {
+               if (lseek(fd, elf->e_shoff, SEEK_SET) == -1)  {
+                       WARN(("lseek section headers"));
+                       return 1;
+               }
+               sz = elf->e_shnum * sizeof(Elf_Shdr);
+
+               shp = ALLOC(sz);
+
+               nr = read(fd, shp, sz);
+               if (nr == -1) {
+                       WARN(("read section headers"));
+                       goto freeshp;
+               }
+               if (nr != sz) {
+                       errno = EIO;
+                       WARN(("read section headers"));
+                       goto freeshp;
+               }
+
+               shpp = maxp;
+               maxp += roundup(sz, ELFROUND);
+
+#ifndef _STANDALONE
+               /* Internalize the section headers. */
+               for (i = 0; i < elf->e_shnum; i++)
+                       internalize_shdr(elf->e_ident[EI_DATA], &shp[i]);
+#endif /* ! _STANDALONE */
+
+               /*
+                * First load the section names section.
+                */
+               if (boot_load_ctf && (elf->e_shstrndx != 0)) {
+                       if (flags & LOAD_SYM) {
+                               if (lseek(fd, shp[elf->e_shstrndx].sh_offset,
+                                   SEEK_SET) == -1) {
+                                       WARN(("lseek symbols"));
+                                       goto freeshp;
+                               }
+                               nr = READ(fd, maxp,
+                                   shp[elf->e_shstrndx].sh_size);
+                               if (nr == -1) {
+                                       WARN(("read symbols"));
+                                       goto freeshp;
+                               }
+                               if (nr !=
+                                   (ssize_t)shp[elf->e_shstrndx].sh_size) {
+                                       errno = EIO;
+                                       WARN(("read symbols"));
+                                       goto freeshp;
+                               }
+
+                               shstr = ALLOC(shp[elf->e_shstrndx].sh_size);
+                               if (lseek(fd, shp[elf->e_shstrndx].sh_offset,
+                                   SEEK_SET) == -1) {
+                                       WARN(("lseek symbols"));
+                                       goto freeshp;
+                               }
+                               nr = read(fd, shstr,
+                                   shp[elf->e_shstrndx].sh_size);
+                               if (nr == -1) {
+                                       WARN(("read symbols"));
+                                       goto freeshp;
+                               }
+                       }
+                       shp[elf->e_shstrndx].sh_offset = maxp - elfp;
+                       maxp += roundup(shp[elf->e_shstrndx].sh_size, ELFROUND);
+               }
+
+               /*
+                * Now load the symbol sections themselves.  Make sure
+                * the sections are aligned. Don't bother with any
+                * string table that isn't referenced by a symbol
+                * table.
+                */
+               for (first = 1, i = 0; i < elf->e_shnum; i++) {
+                       if (i == elf->e_shstrndx) {
+                           /* already loaded this section */
+                           continue;
+                       }
+                       switch (shp[i].sh_type) {
+                       case SHT_PROGBITS:
+                               if (boot_load_ctf && shstr) {
+                                       /* got a CTF section? */
+                                       if (strncmp(".SUNW_ctf",
+                                                   &shstr[shp[i].sh_name],
+                                                   10) == 0) {
+                                               goto havesym;
+                                       }
+                               }
+
+                               /* Not loading this, so zero out the offset. */
+                               shp[i].sh_offset = 0;
+                               break;
+                       case SHT_STRTAB:
+                               for (j = 0; j < elf->e_shnum; j++)
+                                       if (shp[j].sh_type == SHT_SYMTAB &&
+                                           shp[j].sh_link == (unsigned int)i)
+                                               goto havesym;
+                               /* FALLTHROUGH */
+                       default:
+                               /* Not loading this, so zero out the offset. */
+                               shp[i].sh_offset = 0;
+                               break;
+                       havesym:
+                       case SHT_SYMTAB:
+                               if (flags & LOAD_SYM) {
+                                       PROGRESS(("%s%ld", first ? " [" : "+",
+                                           (u_long)shp[i].sh_size));
+                                       if (lseek(fd, shp[i].sh_offset,
+                                           SEEK_SET) == -1) {
+                                               WARN(("lseek symbols"));
+                                               goto freeshp;
+                                       }
+                                       nr = READ(fd, maxp, shp[i].sh_size);
+                                       if (nr == -1) {
+                                               WARN(("read symbols"));
+                                               goto freeshp;
+                                       }
+                                       if (nr != (ssize_t)shp[i].sh_size) {
+                                               errno = EIO;
+                                               WARN(("read symbols"));
+                                               goto freeshp;
+                                       }
+                               }
+                               shp[i].sh_offset = maxp - elfp;
+                               maxp += roundup(shp[i].sh_size, ELFROUND);
+                               first = 0;
+                               break;
+                       case SHT_NOTE:
+                               if ((flags & LOAD_NOTE) == 0)
+                                       break;
+                               if (shp[i].sh_size < sizeof(note)) {
+                                       shp[i].sh_offset = 0;
+                                       break;
+                               }
+                               if (lseek(fd, shp[i].sh_offset, SEEK_SET)
+                                   == -1) {
+                                       WARN(("lseek note"));
+                                       goto freeshp;
+                               }
+                               nr = read(fd, &note, sizeof(note));
+                               if (nr == -1) {
+                                       WARN(("read note"));
+                                       goto freeshp;
+                               }
+                               if (note.nh.n_namesz ==
+                                   ELF_NOTE_NETBSD_NAMESZ &&
+                                   note.nh.n_descsz ==
+                                   ELF_NOTE_NETBSD_DESCSZ &&
+                                   note.nh.n_type ==
+                                   ELF_NOTE_TYPE_NETBSD_TAG &&
+                                   memcmp(note.name, ELF_NOTE_NETBSD_NAME,
+                                   sizeof(note.name)) == 0) {
+                                       memcpy(&netbsd_version, &note.desc,
+                                           sizeof(netbsd_version));
+                               }
+                               shp[i].sh_offset = 0;
+                               break;
+                       }
+               }
+               if (flags & LOAD_SYM) {
+#ifndef _STANDALONE
+                       /* Externalize the section headers. */
+                       for (i = 0; i < elf->e_shnum; i++)
+                               externalize_shdr(elf->e_ident[EI_DATA],
+                                   &shp[i]);
+#endif /* ! _STANDALONE */
+                       BCOPY(shp, shpp, sz);
+
+                       if (first == 0)
+                               PROGRESS(("]"));
+               }
+               DEALLOC(shp, sz);
+       }
+       
+       if (shstr) {
+           DEALLOC(shstr, shp[elf->e_shstrndx].sh_size);
+       }
+
+       /*
+        * Frob the copied ELF header to give information relative
+        * to elfp.
+        */
+       if (flags & LOAD_HDR) {
+               elf->e_phoff = 0;
+               elf->e_shoff = sizeof(Elf_Ehdr);
+               elf->e_phentsize = 0;
+               elf->e_phnum = 0;
+               externalize_ehdr(elf->e_ident[EI_DATA], elf);
+               BCOPY(elf, elfp, sizeof(*elf));
+               internalize_ehdr(elf->e_ident[EI_DATA], elf);
+       }
+
+       marks[MARK_START] = LOADADDR(minp);
+       marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
+       /*
+        * Since there can be more than one symbol section in the code
+        * and we need to find strtab too in order to do anything
+        * useful with the symbols, we just pass the whole elf
+        * header back and we let the kernel debugger find the
+        * location and number of symbols by itself.
+        */
+       marks[MARK_NSYM] = 1;   /* XXX: Kernel needs >= 0 */
+       marks[MARK_SYM] = LOADADDR(elfp);
+       marks[MARK_END] = LOADADDR(maxp);
+       return 0;
+freephdr:
+       DEALLOC(phdr, sz);
+       return 1;
+freeshp:
+       DEALLOC(shp, sz);
+       return 1;
+}
+
+#ifdef TEST
+#include <stdlib.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdio.h>
+u_int32_t netbsd_version;
+int
+main(int argc, char *argv[])
+{
+       int fd;
+       u_long marks[MARK_MAX];
+       Elf_Ehdr elf;
+       if (argc != 2) {
+               (void)fprintf(stderr, "Usage: %s <file>\n", getprogname());
+               return 1;
+       }
+       if ((fd = open(argv[1], O_RDONLY)) == -1)
+               err(1, "Can't open `%s'", argv[1]);
+       if (read(fd, &elf, sizeof(elf)) != sizeof(elf))
+               err(1, "Can't read `%s'", argv[1]);
+       memset(marks, 0, sizeof(marks));
+       marks[MARK_START] = (u_long)malloc(2LL * 1024 * 2024 * 1024);
+       ELFNAMEEND(loadfile)(fd, &elf, marks, LOAD_ALL);
+       printf("%d\n", netbsd_version);
+       return 0;
+}
+#endif
+
+#endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */
diff --git a/sys/lib/libsa/loadfile_elf64.c b/sys/lib/libsa/loadfile_elf64.c
new file mode 100644 (file)
index 0000000..28a67cd
--- /dev/null
@@ -0,0 +1,40 @@
+/* $NetBSD: loadfile_elf64.c,v 1.1 2001/10/31 17:20:50 thorpej Exp $ */
+
+/*
+ * Copyright 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed for the NetBSD Project by
+ *     Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define        ELFSIZE 64
+
+#include "loadfile_elf32.c"
diff --git a/sys/lib/libsa/lookup_elf32.c b/sys/lib/libsa/lookup_elf32.c
new file mode 100644 (file)
index 0000000..46dd4b6
--- /dev/null
@@ -0,0 +1,96 @@
+/* $NetBSD: lookup_elf32.c,v 1.3 2010/02/11 21:28:16 martin Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Martin Husemann.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* If not included by lookup_elf64.c, ELFSIZE won't be defined. */
+#ifndef ELFSIZE
+#define        ELFSIZE 32
+#endif
+
+#include <lib/libkern/libkern.h>
+#include <sys/param.h>
+#include <sys/exec_elf.h>
+
+#if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \
+    ((ELFSIZE == 64) && defined(BOOT_ELF64))
+
+void * ELFNAMEEND(lookup_symbol)(const char *, void *, void *);
+
+void *
+ELFNAMEEND(lookup_symbol)(const char *symname, void *sstab, void *estab)
+{
+       Elf_Ehdr *elf;
+       Elf_Shdr *shp;
+       Elf_Sym *symtab_start, *symtab_end, *sp;
+       char *strtab_start, *strtab_end;
+       int i, j;
+
+       elf = sstab;
+       if (elf->e_shoff == 0)
+               return NULL;
+
+       switch (elf->e_machine) {
+       ELFDEFNNAME(MACHDEP_ID_CASES)
+       default:
+               return NULL;
+       }
+
+       symtab_start = symtab_end = NULL;
+       strtab_start = strtab_end = NULL;
+
+       shp = (Elf_Shdr *)((char *)sstab + elf->e_shoff);
+       for (i = 0; i < elf->e_shnum; i++) {
+               if (shp[i].sh_type != SHT_SYMTAB)
+                       continue;
+               if (shp[i].sh_offset == 0)
+                       continue;
+               symtab_start = (Elf_Sym*)((char*)sstab + shp[i].sh_offset);
+               symtab_end = (Elf_Sym*)((char*)sstab + shp[i].sh_offset
+                       + shp[i].sh_size);
+               j = shp[i].sh_link;
+               if (shp[j].sh_offset == 0)
+                       continue;
+               strtab_start = (char*)sstab + shp[j].sh_offset;
+               strtab_end = (char*)sstab + shp[j].sh_offset + shp[j].sh_size;
+               break;
+       }
+
+       if (!symtab_start || !strtab_start)
+               return NULL;
+
+       for (sp = symtab_start; sp < symtab_end; sp++)
+               if (sp->st_name != 0 &&
+                   strcmp(strtab_start + sp->st_name, symname) == 0)
+                       return (void*)(uintptr_t)sp->st_value;
+
+       return NULL;
+}
+
+#endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */
diff --git a/sys/lib/libsa/lookup_elf64.c b/sys/lib/libsa/lookup_elf64.c
new file mode 100644 (file)
index 0000000..24b5399
--- /dev/null
@@ -0,0 +1,33 @@
+/* $NetBSD: lookup_elf64.c,v 1.1 2010/02/10 21:54:47 martin Exp $ */
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Martin Husemann.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define        ELFSIZE 64
+
+#include "lookup_elf32.c"
diff --git a/sys/lib/libsa/ls.c b/sys/lib/libsa/ls.c
new file mode 100644 (file)
index 0000000..dbed957
--- /dev/null
@@ -0,0 +1,161 @@
+/* $NetBSD: ls.c,v 1.3 2011/12/25 06:09:08 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2011
+ *      The NetBSD Foundation, Inc. All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Martin Husemann.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "stand.h"
+#include <sys/stat.h>
+#include <lib/libkern/libkern.h>
+
+void
+ls(const char *path)
+{
+       int             fd;
+       struct stat     sb;
+       size_t          size;
+       const char      *fname = 0;
+       char            *p;
+       struct open_file *f;
+
+       if ((fd = open(path, 0)) < 0
+           || fstat(fd, &sb) < 0
+           || (sb.st_mode & S_IFMT) != S_IFDIR) {
+               /* Path supplied isn't a directory, open parent
+                  directory and list matching files. */
+               if (fd >= 0)
+                       close(fd);
+               fname = strrchr(path, '/');
+               if (fname) {
+                       size = fname - path;
+                       p = alloc(size + 1);
+                       if (!p)
+                               goto out;
+                       memcpy(p, path, size);
+                       p[size] = 0;
+                       fd = open(p, 0);
+                       dealloc(p, size + 1);
+               } else {
+                       fd = open("", 0);
+                       fname = path;
+               }
+
+               if (fd < 0) {
+                       printf("ls: %s\n", strerror(errno));
+                       return;
+               }
+               if (fstat(fd, &sb) < 0) {
+                       printf("stat: %s\n", strerror(errno));
+                       goto out;
+               }
+               if ((sb.st_mode & S_IFMT) != S_IFDIR) {
+                       printf("%s: %s\n", path, strerror(ENOTDIR));
+                       goto out;
+               }
+       }
+
+       f = &files[fd];
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+               errno = EBADF;
+               goto out;
+       }
+#endif
+
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       /* operation not defined on raw devices */
+       if (f->f_flags & F_RAW) {
+               errno = EOPNOTSUPP;
+               goto out;
+       }
+#endif
+
+       if (FS_LS(f->f_ops) != NULL)
+               FS_LS(f->f_ops)(f, fname);
+       else
+               printf("no ls support for this file system\n");
+
+out:
+       close(fd);
+}
diff --git a/sys/lib/libsa/lseek.c b/sys/lib/libsa/lseek.c
new file mode 100644 (file)
index 0000000..eb3f22f
--- /dev/null
@@ -0,0 +1,103 @@
+/*     $NetBSD: lseek.c,v 1.11 2007/12/02 04:59:26 tsutsui Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)lseek.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+off_t
+#ifndef __INTERNAL_LIBSA_CREAD
+lseek(int fd, off_t offset, int where)
+#else
+olseek(int fd, off_t offset, int where)
+#endif
+{
+       struct open_file *f = &files[fd];
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       if (f->f_flags & F_RAW) {
+               /*
+                * On RAW devices, update internal offset.
+                */
+               switch (where) {
+               case SEEK_SET:
+                       f->f_offset = offset;
+                       break;
+               case SEEK_CUR:
+                       f->f_offset += offset;
+                       break;
+               case SEEK_END:
+               default:
+                       errno = EOFFSET;
+                       return -1;
+               }
+               return f->f_offset;
+       }
+#endif
+
+       return FS_SEEK(f->f_ops)(f, offset, where);
+}
diff --git a/sys/lib/libsa/minixfs3.c b/sys/lib/libsa/minixfs3.c
new file mode 100644 (file)
index 0000000..a722173
--- /dev/null
@@ -0,0 +1,991 @@
+/*     $NetBSD$ */
+
+/*-
+ * Copyright (c) 2012
+ *     Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved.
+ *
+ * Author: Evgeniy Ivanov (based on libsa/ext2fs.c).
+ *
+ * This code is derived from src/sys/lib/libsa/ext2fs.c contributed to 
+ * The NetBSD Foundation, see copyrights below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * Copyright (c) 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: David Golub
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ *     Stand-alone file reading package for MFS file system.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "minixfs3.h"
+
+#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
+#define LIBSA_NO_FS_SYMLINK
+#endif
+
+#if defined(LIBSA_NO_TWIDDLE)
+#define twiddle()
+#endif
+
+typedef uint32_t       ino32_t;
+#ifndef FSBTODB
+#define FSBTODB(fs, indp) fsbtodb(fs, indp)
+#endif
+
+/*
+ * To avoid having a lot of filesystem-block sized buffers lurking (which
+ * could be 32k) we only keep a few entries of the indirect block map.
+ * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
+ * ~13 times pulling in a 6M kernel.
+ * The cache size must be smaller than the smallest filesystem block,
+ * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
+ */
+#define LN2_IND_CACHE_SZ       6
+#define IND_CACHE_SZ           (1 << LN2_IND_CACHE_SZ)
+#define IND_CACHE_MASK         (IND_CACHE_SZ - 1)
+
+/*
+ * In-core open file.
+ */
+struct file {
+       off_t           f_seekp;        /* seek pointer */
+       struct mfs_sblock  *f_fs;       /* pointer to super-block */
+       struct mfs_dinode  f_di;        /* copy of on-disk inode */
+       uint            f_nishift;      /* for blocks in indirect block */
+       block_t         f_ind_cache_block;
+       block_t         f_ind_cache[IND_CACHE_SZ];
+
+       char            *f_buf;         /* buffer for data block */
+       size_t          f_buf_size;     /* size of data block */
+       daddr_t         f_buf_blkno;    /* block number of data block */
+};
+
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+       entry_t *e_next;
+       ino32_t e_ino;
+       char    e_name[1];
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+       char fc, pc;
+
+       do {
+               fc = *fname++;
+               pc = *pattern++;
+               if (!fc && !pc)
+                       return 1;
+               if (pc == '?' && fc)
+                       pc = fc;
+       } while (fc == pc);
+
+       if (pc != '*')
+               return 0;
+       /*
+        * Too hard (and unnecessary really) too check for "*?name" etc....
+        * "**" will look for a '*' and "*?" a '?'
+        */
+       pc = *pattern++;
+       if (!pc)
+               return 1;
+       while ((fname = strchr(fname, pc)))
+               if (fn_match(++fname, pattern))
+                       return 1;
+       return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
+
+static int read_inode(ino32_t, struct open_file *);
+static int block_map(struct open_file *, block_t, block_t *);
+static int buf_read_file(struct open_file *, char **, size_t *);
+static int search_directory(const char *, int, struct open_file *, ino32_t *);
+static int read_sblock(struct open_file *, struct mfs_sblock *);
+
+/*
+ * Read a new inode into a file structure.
+ */
+static int
+read_inode(ino32_t inumber, struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct mfs_sblock *fs = fp->f_fs;
+       char *buf;
+       size_t rsize;
+       int rc;
+       daddr_t inode_sector;
+       struct mfs_dinode *dip;
+
+       inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
+
+       /*
+        * Read inode and save it.
+        */
+       buf = fp->f_buf;
+       twiddle();
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+           inode_sector, fs->mfs_block_size, buf, &rsize);
+       if (rc)
+               return rc;
+       if (rsize != fs->mfs_block_size)
+               return EIO;
+
+       dip = (struct mfs_dinode *)(buf +
+           INODE_SIZE * ino_to_fsbo(fs, inumber));
+       mfs_iload(dip, &fp->f_di);
+
+       /*
+        * Clear out the old buffers
+        */
+       fp->f_ind_cache_block = ~0;
+       fp->f_buf_blkno = -1;
+       return rc;
+}
+
+/*
+ * Given an offset in a file, find the disk block number (not zone!)
+ * that contains that block.
+ */
+static int
+block_map(struct open_file *f, block_t file_block, block_t *disk_block_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct mfs_sblock *fs = fp->f_fs;
+       uint level;
+       block_t ind_cache;
+       block_t ind_block_num;
+       zone_t zone;
+       size_t rsize;
+       int rc;
+       int boff;
+       int scale = fs->mfs_log_zone_size; /* for block-zone conversion */
+       block_t *buf = (void *)fp->f_buf;
+
+       /*
+        * Index structure of an inode:
+        *
+        * mdi_blocks[0..NR_DZONES-1]
+        *                      hold zone numbers for zones
+        *                      0..NR_DZONES-1
+        *
+        * mdi_blocks[NR_DZONES+0]
+        *                      block NDADDR+0 is the single indirect block
+        *                      holds zone numbers for zones
+        *                      NR_DZONES .. NR_DZONES + NINDIR(fs)-1
+        *
+        * mdi_blocks[NR_DZONES+1]
+        *                      block NDADDR+1 is the double indirect block
+        *                      holds zone numbers for INDEX blocks for zones
+        *                      NR_DZONES + NINDIR(fs) ..
+        *                      NR_TZONES + NINDIR(fs) + NINDIR(fs)**2 - 1
+        */
+
+       zone = file_block >> scale;
+       boff = (int) (file_block - (zone << scale) ); /* relative blk in zone */
+
+       if (zone < NR_DZONES) {
+               /* Direct zone */
+               zone_t z = fs2h32(fp->f_di.mdi_zone[zone]);
+               if (z == NO_ZONE) {
+                       *disk_block_p = NO_BLOCK;
+                       return 0;
+               }
+               *disk_block_p = (block_t) ((z << scale) + boff);
+               return 0;
+       }
+
+       zone -= NR_DZONES;
+
+       ind_cache = zone >> LN2_IND_CACHE_SZ;
+       if (ind_cache == fp->f_ind_cache_block) {
+               *disk_block_p =
+                   fs2h32(fp->f_ind_cache[zone & IND_CACHE_MASK]);
+               return 0;
+       }
+
+       for (level = 0;;) {
+               level += fp->f_nishift;
+
+               if (zone < (block_t)1 << level)
+                       break;
+               if (level > NIADDR * fp->f_nishift)
+                       /* Zone number too high */
+                       return EFBIG;
+               zone -= (block_t)1 << level;
+       }
+
+       ind_block_num =
+           fs2h32(fp->f_di.mdi_zone[NR_DZONES + (level / fp->f_nishift - 1)]);
+
+       for (;;) {
+               level -= fp->f_nishift;
+               if (ind_block_num == 0) {
+                       *disk_block_p = NO_BLOCK;       /* missing */
+                       return 0;
+               }
+
+               twiddle();
+               /*
+                * If we were feeling brave, we could work out the number
+                * of the disk sector and read a single disk sector instead
+                * of a filesystem block.
+                * However we don't do this very often anyway...
+                */
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                       FSBTODB(fs, ind_block_num), fs->mfs_block_size,
+                       buf, &rsize);
+               if (rc)
+                       return rc;
+               if (rsize != fs->mfs_block_size)
+                       return EIO;
+
+               ind_block_num = fs2h32(buf[zone >> level]);
+               if (level == 0)
+                       break;
+               zone &= (1 << level) - 1;
+       }
+
+       /* Save the part of the block that contains this sector */
+       memcpy(fp->f_ind_cache, &buf[zone & ~IND_CACHE_MASK],
+           IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
+       fp->f_ind_cache_block = ind_cache;
+
+       zone = (zone_t)ind_block_num;
+       *disk_block_p = (block_t)((zone << scale) + boff);
+       return 0;
+}
+
+/*
+ * Read a portion of a file into an internal buffer.
+ * Return the location in the buffer and the amount in the buffer.
+ */
+static int
+buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct mfs_sblock *fs = fp->f_fs;
+       long off;
+       block_t file_block;
+       block_t disk_block;
+       size_t block_size;
+       int rc;
+
+       off = blkoff(fs, fp->f_seekp);
+       file_block = lblkno(fs, fp->f_seekp);
+       block_size = fs->mfs_block_size;
+
+       if (file_block != fp->f_buf_blkno) {
+               rc = block_map(f, file_block, &disk_block);
+               if (rc)
+                       return rc;
+
+               if (disk_block == 0) {
+                       memset(fp->f_buf, 0, block_size);
+                       fp->f_buf_size = block_size;
+               } else {
+                       twiddle();
+                       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                               FSBTODB(fs, disk_block),
+                               block_size, fp->f_buf, &fp->f_buf_size);
+                       if (rc)
+                               return rc;
+               }
+
+               fp->f_buf_blkno = file_block;
+       }
+
+       /*
+        * Return address of byte in buffer corresponding to
+        * offset, and size of remainder of buffer after that
+        * byte.
+        */
+       *buf_p = fp->f_buf + off;
+       *size_p = block_size - off;
+
+       /*
+        * But truncate buffer at end of file.
+        */
+       if (*size_p > fp->f_di.mdi_size - fp->f_seekp)
+               *size_p = fp->f_di.mdi_size - fp->f_seekp;
+
+       return 0;
+}
+
+/*
+ * Search a directory for a name and return its
+ * inode number.
+ */
+static int
+search_directory(const char *name, int length, struct open_file *f,
+       ino32_t *inumber_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct mfs_sblock *fs = fp->f_fs;
+       struct mfs_direct *dp;
+       struct mfs_direct *dbuf;
+       size_t buf_size;
+       int namlen;
+       int rc;
+
+       fp->f_seekp = 0;
+
+       while (fp->f_seekp < (off_t)fp->f_di.mdi_size) {
+               rc = buf_read_file(f, (char**)&dbuf, &buf_size);
+               if (rc)
+                       return rc;
+               if (buf_size == 0)
+                       return EIO;
+
+               /* XXX we assume, that buf_read_file reads an fs block and
+                * doesn't truncate buffer. Currently i_size in MFS doesn't
+                * the same as size of allocated blocks, it makes buf_read_file
+                * to truncate buf_size.
+                */
+               if (buf_size < fs->mfs_block_size)
+                       buf_size = fs->mfs_block_size;
+
+               for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) {
+                       char *cp;
+                       if (fs2h32(dp->mfsd_ino) == (ino32_t) 0)
+                               continue;
+                       /* Compute the length of the name */
+                       cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name));
+                       if (cp == NULL)
+                               namlen = sizeof(dp->mfsd_name);
+                       else
+                               namlen = cp - (dp->mfsd_name);
+
+                       if (namlen == length &&
+                           !memcmp(name, dp->mfsd_name, length)) {
+                               /* found entry */
+                               *inumber_p = fs2h32(dp->mfsd_ino);
+                               return 0;
+                       }
+               }
+               fp->f_seekp += buf_size;
+       }
+       return ENOENT;
+}
+
+int
+read_sblock(struct open_file *f, struct mfs_sblock *fs)
+{
+       static uint8_t sbbuf[MINBSIZE];
+       size_t buf_size;
+       int rc;
+
+       /* We must read amount multiple of sector size, hence we can't
+        * read SBSIZE and read MINBSIZE.
+        */
+       if (SBSIZE > MINBSIZE)
+               return EINVAL;
+
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+           SUPER_BLOCK_OFF / DEV_BSIZE, MINBSIZE, sbbuf, &buf_size);
+       if (rc)
+               return rc;
+
+       if (buf_size != MINBSIZE)
+               return EIO;
+
+       mfs_sbload((void *)sbbuf, fs);
+
+       if (fs->mfs_magic != SUPER_MAGIC)
+               return EINVAL;
+       if (fs->mfs_block_size < MINBSIZE)
+               return EINVAL;
+       if ((fs->mfs_block_size % 512) != 0)
+               return EINVAL;
+       if (SBSIZE > fs->mfs_block_size)
+               return EINVAL;
+       if ((fs->mfs_block_size % INODE_SIZE) != 0)
+               return EINVAL;
+
+       /* For even larger disks, a similar problem occurs with s_firstdatazone.
+        * If the on-disk field contains zero, we assume that the value was too
+        * large to fit, and compute it on the fly.
+        */
+       if (fs->mfs_firstdatazone_old == 0) {
+               block_t offset;
+               offset = START_BLOCK + fs->mfs_imap_blocks + fs->mfs_zmap_blocks;
+               offset += (fs->mfs_ninodes + fs->mfs_inodes_per_block - 1) /
+                               fs->mfs_inodes_per_block;
+
+               fs->mfs_firstdatazone =
+                       (offset + (1 << fs->mfs_log_zone_size) - 1) >>
+                               fs->mfs_log_zone_size;
+       } else {
+               fs->mfs_firstdatazone = (zone_t) fs->mfs_firstdatazone_old;
+       }
+
+       if (fs->mfs_imap_blocks < 1 || fs->mfs_zmap_blocks < 1
+                       || fs->mfs_ninodes < 1 || fs->mfs_zones < 1
+                       || fs->mfs_firstdatazone <= 4
+                       || fs->mfs_firstdatazone >= fs->mfs_zones
+                       || (unsigned) fs->mfs_log_zone_size > 4)
+               return EINVAL;
+
+       /* compute in-memory mfs_sblock values */
+       fs->mfs_inodes_per_block = fs->mfs_block_size / INODE_SIZE;
+
+
+       {
+               int32_t mult = fs->mfs_block_size >> LOG_MINBSIZE;
+               int ln2 = LOG_MINBSIZE;
+
+               for (; mult != 1; ln2++)
+                       mult >>= 1;
+
+               fs->mfs_bshift = ln2;
+               /* XXX assume hw bsize = 512 */
+               fs->mfs_fsbtodb = ln2 - LOG_MINBSIZE + 1;
+       }
+
+       fs->mfs_qbmask = fs->mfs_block_size - 1;
+       fs->mfs_bmask = ~fs->mfs_qbmask;
+
+       return 0;
+}
+
+/*
+ * Open a file.
+ */
+__compactcall int
+minixfs3_open(const char *path, struct open_file *f)
+{
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       const char *cp, *ncp;
+       int c;
+#endif
+       ino32_t inumber;
+       struct file *fp;
+       struct mfs_sblock *fs;
+       int rc;
+#ifndef LIBSA_NO_FS_SYMLINK
+       ino32_t parent_inumber;
+       int nlinks = 0;
+       char namebuf[MAXPATHLEN+1];
+       char *buf;
+#endif
+
+       /* allocate file system specific data structure */
+       fp = alloc(sizeof(struct file));
+       memset(fp, 0, sizeof(struct file));
+       f->f_fsdata = (void *)fp;
+
+       /* allocate space and read super block */
+       fs = alloc(sizeof(*fs));
+       memset(fs, 0, sizeof(*fs));
+       fp->f_fs = fs;
+       twiddle();
+
+       rc = read_sblock(f, fs);
+       if (rc)
+               goto out;
+
+       /* alloc a block sized buffer used for all fs transfers */
+       fp->f_buf = alloc(fs->mfs_block_size);
+
+       /*
+        * Calculate indirect block levels.
+        */
+       {
+               int32_t mult;
+               int ln2;
+
+               /*
+                * We note that the number of indirect blocks is always
+                * a power of 2.  This lets us use shifts and masks instead
+                * of divide and remainder and avoinds pulling in the
+                * 64bit division routine into the boot code.
+                */
+               mult = NINDIR(fs);
+#ifdef DEBUG
+               if (!powerof2(mult)) {
+                       /* Hummm was't a power of 2 */
+                       rc = EINVAL;
+                       goto out;
+               }
+#endif
+               for (ln2 = 0; mult != 1; ln2++)
+                       mult >>= 1;
+
+               fp->f_nishift = ln2;
+       }
+
+       inumber = ROOT_INODE;
+       if ((rc = read_inode(inumber, f)) != 0)
+               goto out;
+
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       cp = path;
+       while (*cp) {
+
+               /*
+                * Remove extra separators
+                */
+               while (*cp == '/')
+                       cp++;
+               if (*cp == '\0')
+                       break;
+
+               /*
+                * Check that current node is a directory.
+                */
+               if ((fp->f_di.mdi_mode & I_TYPE) != I_DIRECTORY) {
+                       rc = ENOTDIR;
+                       goto out;
+               }
+
+               /*
+                * Get next component of path name.
+                */
+               ncp = cp;
+               while ((c = *cp) != '\0' && c != '/')
+                       cp++;
+
+               /*
+                * Look up component in current directory.
+                * Save directory inumber in case we find a
+                * symbolic link.
+                */
+#ifndef LIBSA_NO_FS_SYMLINK
+               parent_inumber = inumber;
+#endif
+               rc = search_directory(ncp, cp - ncp, f, &inumber);
+               if (rc)
+                       goto out;
+
+               /*
+                * Open next component.
+                */
+               if ((rc = read_inode(inumber, f)) != 0)
+                       goto out;
+
+#ifndef LIBSA_NO_FS_SYMLINK
+               /*
+                * Check for symbolic link.
+                */
+               if ((fp->f_di.mdi_mode & I_TYPE) == I_SYMBOLIC_LINK) {
+                       int link_len = fp->f_di.mdi_size;
+                       int len;
+                       size_t buf_size;
+                       block_t disk_block;
+
+                       len = strlen(cp);
+
+                       if (link_len + len > MAXPATHLEN ||
+                           ++nlinks > MAXSYMLINKS) {
+                               rc = ENOENT;
+                               goto out;
+                       }
+
+                       memmove(&namebuf[link_len], cp, len + 1);
+
+                       /*
+                        * Read file for symbolic link
+                        */
+                       buf = fp->f_buf;
+                       rc = block_map(f, (block_t)0, &disk_block);
+                       if (rc)
+                               goto out;
+
+                       twiddle();
+                       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
+                                       F_READ, FSBTODB(fs, disk_block),
+                                       fs->mfs_block_size, buf, &buf_size);
+                       if (rc)
+                               goto out;
+
+                       memcpy(namebuf, buf, link_len);
+
+                       /*
+                        * If relative pathname, restart at parent directory.
+                        * If absolute pathname, restart at root.
+                        */
+                       cp = namebuf;
+                       if (*cp != '/')
+                               inumber = parent_inumber;
+                       else
+                               inumber = (ino32_t) ROOT_INODE;
+
+                       if ((rc = read_inode(inumber, f)) != 0)
+                               goto out;
+               }
+#endif /* !LIBSA_NO_FS_SYMLINK */
+       }
+
+       /*
+        * Found terminal component.
+        */
+       rc = 0;
+
+#else /* !LIBSA_FS_SINGLECOMPONENT */
+
+       /* look up component in the current (root) directory */
+       rc = search_directory(path, strlen(path), f, &inumber);
+       if (rc)
+               goto out;
+
+       /* open it */
+       rc = read_inode(inumber, f);
+
+#endif /* !LIBSA_FS_SINGLECOMPONENT */
+
+       fp->f_seekp = 0;                /* reset seek pointer */
+
+out:
+       if (rc)
+               minixfs3_close(f);
+
+       return rc;
+}
+
+__compactcall int
+minixfs3_close(struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       f->f_fsdata = NULL;
+       if (fp == NULL)
+               return 0;
+
+       if (fp->f_buf)
+               dealloc(fp->f_buf, fp->f_fs->mfs_block_size);
+       dealloc(fp->f_fs, sizeof(*fp->f_fs));
+       dealloc(fp, sizeof(struct file));
+       return 0;
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+__compactcall int
+minixfs3_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       size_t csize;
+       char *buf;
+       size_t buf_size;
+       int rc = 0;
+       char *addr = start;
+
+       while (size != 0) {
+               if (fp->f_seekp >= (off_t)fp->f_di.mdi_size)
+                       break;
+
+               rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       break;
+
+               csize = size;
+               if (csize > buf_size)
+                       csize = buf_size;
+
+               memcpy(addr, buf, csize);
+
+               fp->f_seekp += csize;
+               addr += csize;
+               size -= csize;
+       }
+
+       if (resid)
+               *resid = size;
+       return rc;
+}
+
+/*
+ * Not implemented.
+ */
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+minixfs3_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+minixfs3_seek(struct open_file *f, off_t offset, int where)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               fp->f_seekp = offset;
+               break;
+       case SEEK_CUR:
+               fp->f_seekp += offset;
+               break;
+       case SEEK_END:
+               fp->f_seekp = fp->f_di.mdi_size - offset;
+               break;
+       default:
+               return -1;
+       }
+       return fp->f_seekp;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+__compactcall int
+minixfs3_stat(struct open_file *f, struct stat *sb)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       /* only important stuff */
+       memset(sb, 0, sizeof *sb);
+       sb->st_mode = fp->f_di.mdi_mode;
+       sb->st_uid = fp->f_di.mdi_uid;
+       sb->st_gid = fp->f_di.mdi_gid;
+       sb->st_size = fp->f_di.mdi_size;
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+minixfs3_ls(struct open_file *f, const char *pattern)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct mfs_sblock *fs = fp->f_fs;
+       struct mfs_direct *dp;
+       struct mfs_direct *dbuf;
+       size_t buf_size;
+       entry_t *names = 0, *n, **np;
+
+       fp->f_seekp = 0;
+       while (fp->f_seekp < (off_t)fp->f_di.mdi_size) {
+               int rc = buf_read_file(f, (char**)&dbuf, &buf_size);
+               if (rc)
+                       goto out;
+
+               /* XXX we assume, that buf_read_file reads an fs block and
+                * doesn't truncate buffer. Currently i_size in MFS doesn't
+                * the same as size of allocated blocks, it makes buf_read_file
+                * to truncate buf_size.
+                */
+               if (buf_size < fs->mfs_block_size)
+                       buf_size = fs->mfs_block_size;
+
+               for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) {
+                       char *cp;
+                       int namlen;
+
+                       if (fs2h32(dp->mfsd_ino) == 0)
+                               continue;
+
+                       if (pattern && !fn_match(dp->mfsd_name, pattern))
+                               continue;
+
+                       /* Compute the length of the name,
+                        * We don't use strlen and strcpy, because original MFS
+                        * code doesn't.
+                        */
+                       cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name));
+                       if (cp == NULL)
+                               namlen = sizeof(dp->mfsd_name);
+                       else
+                               namlen = cp - (dp->mfsd_name);
+
+                       n = alloc(sizeof *n + namlen);
+                       if (!n) {
+                               printf("%d: %s\n",
+                                       fs2h32(dp->mfsd_ino), dp->mfsd_name);
+                               continue;
+                       }
+                       n->e_ino = fs2h32(dp->mfsd_ino);
+                       strncpy(n->e_name, dp->mfsd_name, namlen);
+                       n->e_name[namlen] = '\0';
+                       for (np = &names; *np; np = &(*np)->e_next) {
+                               if (strcmp(n->e_name, (*np)->e_name) < 0)
+                                       break;
+                       }
+                       n->e_next = *np;
+                       *np = n;
+               }
+               fp->f_seekp += buf_size;
+       }
+
+       if (names) {
+               entry_t *p_names = names;
+               do {
+                       n = p_names;
+                       printf("%d: %s\n",
+                               n->e_ino, n->e_name);
+                       p_names = n->e_next;
+               } while (p_names);
+       } else {
+               printf("not found\n");
+       }
+out:
+       if (names) {
+               do {
+                       n = names;
+                       names = n->e_next;
+                       dealloc(n, 0);
+               } while (names);
+       }
+       return;
+}
+#endif
+
+/*
+ * byte swap functions for big endian machines
+ * (mfs is always little endian)
+ */
+
+/* These functions are only needed if native byte order is not big endian */
+#if BYTE_ORDER == BIG_ENDIAN
+void
+minixfs3_sb_bswap(struct mfs_sblock *old, struct mfs_sblock *new)
+{
+       new->mfs_ninodes        =       bswap32(old->mfs_ninodes);
+       new->mfs_nzones         =       bswap16(old->mfs_nzones);
+       new->mfs_imap_blocks    =       bswap16(old->mfs_imap_blocks);
+       new->mfs_zmap_blocks    =       bswap16(old->mfs_zmap_blocks);
+       new->mfs_firstdatazone_old =    bswap16(old->mfs_firstdatazone_old);
+       new->mfs_log_zone_size  =       bswap16(old->mfs_log_zone_size);
+       new->mfs_max_size       =       bswap32(old->mfs_max_size);
+       new->mfs_zones          =       bswap32(old->mfs_zones);
+       new->mfs_magic          =       bswap16(old->mfs_magic);
+       new->mfs_block_size     =       bswap16(old->mfs_block_size);
+       new->mfs_disk_version   =       old->mfs_disk_version;
+}
+
+void minixfs3_i_bswap(struct mfs_dinode *old, struct mfs_dinode *new)
+{
+       int i;
+
+       new->mdi_mode           =       bswap16(old->mdi_mode);
+       new->mdi_nlinks         =       bswap16(old->mdi_nlinks);
+       new->mdi_uid            =       bswap16(old->mdi_uid);
+       new->mdi_gid            =       bswap16(old->mdi_gid);
+       new->mdi_size           =       bswap32(old->mdi_size);
+       new->mdi_atime          =       bswap32(old->mdi_atime);
+       new->mdi_mtime          =       bswap32(old->mdi_mtime);
+       new->mdi_ctime          =       bswap32(old->mdi_ctime);
+
+       /* We don't swap here, because indirects must be swapped later
+        * anyway, hence everything is done by block_map().
+        */
+       for (i = 0; i < NR_TZONES; i++)
+               new->mdi_zone[i] = old->mdi_zone[i];
+}
+#endif
diff --git a/sys/lib/libsa/minixfs3.h b/sys/lib/libsa/minixfs3.h
new file mode 100644 (file)
index 0000000..aef8a54
--- /dev/null
@@ -0,0 +1,176 @@
+/*     $NetBSD$ */
+
+/*-
+ * Copyright (c) 2012
+ *     Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved.
+ *
+ * Author: Evgeniy Ivanov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MINIX_FS_3_H
+#define MINIX_FS_3_H
+
+FS_DEF(minixfs3);
+
+typedef uint32_t zone_t;
+typedef uint16_t zone1_t;
+typedef uint32_t block_t;
+
+#define NR_DZONES      7       /* # direct zone numbers in an inode */
+#define NR_TZONES      10      /* total # zone numbers in an inode */
+#define NIADDR         2       /* Indirect addresses in inode */
+
+struct mfs_dinode {
+       uint16_t  mdi_mode;     /* file type, protection, etc. */
+       uint16_t  mdi_nlinks;   /* how many links to this file */
+       int16_t   mdi_uid;      /* user id of the file's owner */
+       uint16_t  mdi_gid;      /* group number */
+       uint32_t  mdi_size;     /* current file size in bytes */
+       uint32_t  mdi_atime;    /* time of last access */
+       uint32_t  mdi_mtime;    /* when was file data last changed */
+       uint32_t  mdi_ctime;    /* when was inode itself changed */
+       zone_t    mdi_zone[NR_TZONES]; /* zone numbers for direct, ind, and
+                                               dbl ind */
+};
+
+/* Maximum Minix MFS on-disk directory filename.
+ * MFS uses 'struct direct' to write and parse
+ * directory entries, so this can't be changed
+ * without breaking filesystems.
+ */
+#define MFS_DIRSIZ     60
+
+struct mfs_direct {
+       uint32_t  mfsd_ino;
+       char      mfsd_name[MFS_DIRSIZ];
+} __packed;
+
+struct mfs_sblock {
+       uint32_t  mfs_ninodes;          /* # usable inodes on the minor device */
+       zone1_t   mfs_nzones;           /* total device size, including bit maps etc */
+       int16_t   mfs_imap_blocks;      /* # of blocks used by inode bit map */
+       int16_t   mfs_zmap_blocks;      /* # of blocks used by zone bit map */
+       zone1_t   mfs_firstdatazone_old;/* number of first data zone (small) */
+       int16_t   mfs_log_zone_size;    /* log2 of blocks/zone */
+       int16_t   mfs_pad;              /* try to avoid compiler-dependent padding */
+       int32_t   mfs_max_size;         /* maximum file size on this device */
+       zone_t    mfs_zones;            /* number of zones (replaces s_nzones in V2) */
+       int16_t   mfs_magic;            /* magic number to recognize super-blocks */
+       int16_t   mfs_pad2;             /* try to avoid compiler-dependent padding */
+       uint16_t  mfs_block_size;       /* block size in bytes. */
+       char      mfs_disk_version;     /* filesystem format sub-version */
+
+  /* The following items are only used when the super_block is in memory,
+   * mfs_inodes_per_block must be the firs one (see SBSIZE)
+   */
+       unsigned mfs_inodes_per_block;  /* precalculated from magic number */
+       zone_t   mfs_firstdatazone;     /* number of first data zone (big) */
+       int32_t  mfs_bshift;            /* ``lblkno'' calc of logical blkno */
+       int32_t  mfs_bmask;             /* ``blkoff'' calc of blk offsets */
+       int64_t  mfs_qbmask;            /* ~fs_bmask - for use with quad size */
+       int32_t  mfs_fsbtodb;           /* fsbtodb and dbtofsb shift constant */
+};
+
+#define LOG_MINBSIZE   10
+#define MINBSIZE       (1 << LOG_MINBSIZE)
+
+#define SUPER_MAGIC    0x4d5a  /* magic # for MFSv3 file systems */
+
+#define ROOT_INODE     ((uint32_t) 1)  /* inode number for root directory */
+#define SUPER_BLOCK_OFF (1024)         /* bytes offset */
+#define START_BLOCK    ((block_t) 2)   /* first fs block (not counting SB) */
+
+/* # bytes/dir entry */
+#define DIR_ENTRY_SIZE         sizeof(struct mfs_direct)
+/* # dir entries/blk */
+#define NR_DIR_ENTRIES(fs)     ((fs)->mfs_block_size/DIR_ENTRY_SIZE)
+/* mfs_sblock on-disk part size */
+#define SBSIZE                 offsetof(struct mfs_sblock, mfs_inodes_per_block)
+
+#define ZONE_NUM_SIZE          sizeof(zone_t) /* # bytes in zone  */
+#define INODE_SIZE             sizeof(struct mfs_dinode) /* bytes in dsk ino */
+/* # zones/indir block */
+#define NINDIR(fs)             ((fs)->mfs_block_size/ZONE_NUM_SIZE)
+
+#define NO_ZONE                        ((zone_t) 0)    /* absence of a zone number */
+#define NO_BLOCK               ((block_t) 0)   /* absence of a block number */
+
+/* Turn file system block numbers into disk block addresses */
+#define fsbtodb(fs, b) ((b) << (fs)->mfs_fsbtodb)
+
+#define        ino_to_fsba(fs, x)                                              \
+       (((x) - 1) / (fs)->mfs_inodes_per_block +                       \
+       START_BLOCK + (fs)->mfs_imap_blocks + (fs)->mfs_zmap_blocks)
+#define        ino_to_fsbo(fs, x)      (((x) - 1) % (fs)->mfs_inodes_per_block)
+
+/*
+ * MFS metadatas are stored in little-endian byte order. These macros
+ * helps reading theses metadatas.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#      define fs2h16(x) (x)
+#      define fs2h32(x) (x)
+#      define mfs_sbload(old, new)     \
+               memcpy((new), (old), SBSIZE);
+#      define mfs_iload(old, new)      \
+               memcpy((new),(old),sizeof(struct mfs_dinode))
+#else
+void minixfs3_sb_bswap(struct mfs_sblock *, struct mfs_sblock *);
+void minixfs3_i_bswap(struct mfs_dinode *, struct mfs_dinode *);
+#      define fs2h16(x) bswap16(x)
+#      define fs2h32(x) bswap32(x)
+#      define mfs_sbload(old, new) minixfs3_sb_bswap((old), (new))
+#      define mfs_iload(old, new) minixfs3_i_bswap((old), (new))
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * The following macros optimize certain frequently calculated
+ * quantities by using shifts and masks in place of divisions
+ * modulos and multiplications.
+ */
+#define blkoff(fs, loc)                /* calculates (loc % fs->mfs_bsize) */ \
+       ((loc) & (fs)->mfs_qbmask)
+#define lblkno(fs, loc)                /* calculates (loc / fs->mfs_bsize) */ \
+       ((loc) >> (fs)->mfs_bshift)
+
+/* Flag bits for i_mode in the inode. */
+#define I_TYPE          0170000 /* this field gives inode type */
+#define I_UNIX_SOCKET   0140000 /* unix domain socket */
+#define I_SYMBOLIC_LINK 0120000 /* file is a symbolic link */
+#define I_REGULAR       0100000 /* regular file, not dir or special */
+#define I_BLOCK_SPECIAL 0060000 /* block special file */
+#define I_DIRECTORY     0040000 /* file is a directory */
+#define I_CHAR_SPECIAL  0020000 /* character special file */
+#define I_NAMED_PIPE    0010000 /* named pipe (FIFO) */
+#define I_SET_UID_BIT   0004000 /* set effective uid_t on exec */
+#define I_SET_GID_BIT   0002000 /* set effective gid_t on exec */
+#define I_SET_STCKY_BIT 0001000 /* sticky bit */
+#define ALL_MODES       0007777 /* all bits for user, group and others */
+#define RWX_MODES       0000777 /* mode bits for RWX only */
+#define R_BIT           0000004 /* Rwx protection bit */
+#define W_BIT           0000002 /* rWx protection bit */
+#define X_BIT           0000001 /* rwX protection bit */
+#define I_NOT_ALLOC     0000000 /* this inode is free */
+
+#endif /* MINIX_FS_3_H */
diff --git a/sys/lib/libsa/net.c b/sys/lib/libsa/net.c
new file mode 100644 (file)
index 0000000..8d03711
--- /dev/null
@@ -0,0 +1,141 @@
+/*     $NetBSD: net.c,v 1.35 2009/04/11 10:57:55 lukem Exp $   */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#ifdef _STANDALONE
+#include "stand.h"
+#define delay()
+#else
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#define panic printf
+#define delay() usleep(100000)
+#define getsecs() time(NULL)
+#endif
+
+#include "net.h"
+
+/*
+ * Send a packet and wait for a reply, with exponential backoff.
+ *
+ * The send routine must return the actual number of bytes written,
+ * or -1 on error.
+ *
+ * The receive routine can indicate success by returning the number of
+ * bytes read; it can return 0 to indicate EOF; it can return -1 with a
+ * non-zero errno to indicate failure; finally, it can return -1 with a
+ * zero errno to indicate it isn't done yet.
+ */
+ssize_t
+sendrecv(struct iodesc *d,
+       ssize_t (*sproc)(struct iodesc *, void *, size_t),
+       void *sbuf, size_t ssize,
+       ssize_t (*rproc)(struct iodesc *, void *, size_t, saseconds_t),
+       void *rbuf, size_t rsize)
+{
+       ssize_t cc;
+       satime_t t, tlast;
+       saseconds_t tmo, tleft;
+
+#ifdef NET_DEBUG
+       if (debug)
+               printf("sendrecv: called\n");
+#endif
+
+       tmo = MINTMO;
+       tlast = 0;
+       tleft = 0;
+       t = getsecs();
+       for (;;) {
+               if (tleft <= 0) {
+                       if (tmo >= MAXTMO) {
+                               errno = ETIMEDOUT;
+                               return -1;
+                       }
+                       cc = (*sproc)(d, sbuf, ssize);
+
+                       tleft = tmo;
+                       tmo <<= 1;
+                       if (tmo > MAXTMO)
+                               tmo = MAXTMO;
+
+                       if (cc == -1) {
+                               /* Error on transmit; wait before retrying */
+                               while ((getsecs() - t) < tmo)
+                                       delay();
+                               tleft = 0;
+                               continue;
+                       }
+                       if ((size_t)cc < ssize)
+                               panic("sendrecv: short write! (%zd < %zu)",
+                                   cc, ssize);
+
+                       tlast = t;
+               }
+
+               /* Try to get a packet and process it. */
+               cc = (*rproc)(d, rbuf, rsize, tleft);
+               /* Return on data, EOF or real error. */
+               if (cc != -1 || errno != 0)
+                       return cc;
+
+               /* Timed out or didn't get the packet we're waiting for */
+               t = getsecs();
+               tleft -= t - tlast;
+               tlast = t;
+       }
+}
diff --git a/sys/lib/libsa/net.h b/sys/lib/libsa/net.h
new file mode 100644 (file)
index 0000000..e163c8c
--- /dev/null
@@ -0,0 +1,135 @@
+/*     $NetBSD: net.h,v 1.26 2011/05/11 16:23:40 zoltan Exp $  */
+
+/*
+ * Copyright (c) 1993 Adam Glass
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#ifndef _KERNEL        /* XXX - see <netinet/in.h> */
+#undef __IPADDR
+#define __IPADDR(x)    htonl((u_int32_t)(x))
+#endif
+
+#ifdef _STANDALONE
+#include <lib/libsa/iodesc.h>
+#else
+#include <iodesc.h>
+#endif
+
+#define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
+
+/* Returns true if n_long's on the same net */
+#define        SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m))
+
+#define MACPY(s, d) memcpy(d, s, 6)
+
+#define MAXTMO 20      /* seconds */
+#define MINTMO 2       /* seconds */
+
+#define FNAME_SIZE 128
+#define        IFNAME_SIZE 16
+#define RECV_SIZE 1536 /* XXX delete this */
+
+/*
+ * How much room to leave for headers in UDP packets:
+ *  14: struct ether_header
+ *  20: struct ip
+ *   8: struct udphdr
+ * That's 42 but let's pad it out to 48 bytes.
+ */
+#define ETHERNET_HEADER_SIZE 14
+#define IP_HEADER_SIZE 20
+#define UDP_HEADER_SIZE 8
+
+#define        UDP_TOTAL_HEADER_SIZE (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE)
+
+/*
+ * How much room to leave for headers in TCP packets:
+ *  14: struct ether_header
+ *  20: struct ip
+ *  20: struct tcphdr
+ */
+#define TCP_HEADER_SIZE 20
+
+#define TCP_TOTAL_HEADER_SIZE (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE)
+
+extern u_char bcea[6];
+extern char rootpath[FNAME_SIZE];
+extern char bootfile[FNAME_SIZE];
+extern char hostname[FNAME_SIZE];
+
+/* All of these are in network order. */
+extern struct in_addr myip;
+extern struct in_addr rootip;
+extern struct in_addr gateip;
+extern n_long netmask;
+
+extern int debug;                      /* defined in the machdep sources */
+
+/* ARP/RevARP functions: */
+u_char *arpwhohas(struct iodesc *, struct in_addr);
+void   arp_reply(struct iodesc *, void *);
+int    rarp_getipaddress(int);
+
+/* Link functions: */
+ssize_t sendether(struct iodesc *, void *, size_t, u_char *, int);
+ssize_t readether(struct iodesc *, void *, size_t, saseconds_t, u_int16_t *);
+
+ssize_t        sendip __P((struct iodesc *, void *, size_t, u_int8_t));
+ssize_t        readip __P((struct iodesc *, void *, size_t, time_t, u_int8_t));
+
+ssize_t        sendudp(struct iodesc *, void *, size_t);
+ssize_t        readudp(struct iodesc *, void *, size_t, saseconds_t);
+
+int    tcp_connect __P((struct iodesc *));
+ssize_t        sendtcp __P((struct iodesc *, void *, size_t));
+ssize_t        readtcp __P((struct iodesc *, void *, size_t, time_t));
+
+ssize_t        sendrecv(struct iodesc *, ssize_t (*)(struct iodesc *, void *, size_t),
+    void *, size_t, ssize_t (*)(struct iodesc *, void *, size_t, saseconds_t),
+    void *, size_t);
+
+/* Utilities: */
+char   *ether_sprintf(const u_char *);
+int    ip_cksum(const void *, size_t);
+
+/* Machine-dependent functions: */
+#ifdef _STANDALONE     /* XXX for mount_nfs(8) SMALLPROG hack */
+satime_t       getsecs(void);
+#endif
diff --git a/sys/lib/libsa/netif.c b/sys/lib/libsa/netif.c
new file mode 100644 (file)
index 0000000..ada3136
--- /dev/null
@@ -0,0 +1,322 @@
+/*     $NetBSD: netif.c,v 1.24 2009/01/17 14:00:36 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 1993 Adam Glass
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by Adam Glass.
+ * 4. The name of the Author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+#include <sys/mount.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include "stand.h"
+#include "netif.h"
+
+struct iodesc sockets[SOPEN_MAX];
+#ifdef NETIF_DEBUG
+int netif_debug = 0;
+#endif
+
+/*
+ * netif_init:
+ *
+ * initialize the generic network interface layer
+ */
+
+void
+netif_init(void)
+{
+       struct netif_driver *drv;
+       int d, i;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("netif_init: called\n");
+#endif
+       for (d = 0; d < n_netif_drivers; d++) {
+               drv = netif_drivers[d];
+               for (i = 0; i < drv->netif_nifs; i++)
+                       drv->netif_ifs[i].dif_used = 0;
+       }
+}
+
+int    netif_match(struct netif *, void *);
+
+int
+netif_match(struct netif *nif, void *machdep_hint)
+{
+       struct netif_driver *drv = nif->nif_driver;
+
+#if 0
+       if (netif_debug)
+               printf("%s%d: netif_match (%d)\n", drv->netif_bname,
+                   nif->nif_unit, nif->nif_sel);
+#endif
+       return drv->netif_match(nif, machdep_hint);
+}
+
+struct netif *
+netif_select(void *machdep_hint)
+{
+       int d, u, unit_done, s;
+       struct netif_driver *drv;
+       struct netif cur_if;
+       static struct netif best_if;
+       int best_val;
+       int val;
+
+       best_val = 0;
+       best_if.nif_driver = NULL;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("netif_select: %d interfaces\n", n_netif_drivers);
+#endif
+
+       for (d = 0; d < n_netif_drivers; d++) {
+               cur_if.nif_driver = netif_drivers[d];
+               drv = cur_if.nif_driver;
+
+               for (u = 0; u < drv->netif_nifs; u++) {
+                       cur_if.nif_unit = u;
+                       unit_done = 0;
+
+#ifdef NETIF_DEBUG
+                       if (netif_debug)
+                               printf("\t%s%d:", drv->netif_bname,
+                                   cur_if.nif_unit);
+#endif
+
+                       for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) {
+                               cur_if.nif_sel = s;
+
+                               if (drv->netif_ifs[u].dif_used & (1 << s)) {
+#ifdef NETIF_DEBUG
+                                       if (netif_debug)
+                                               printf(" [%d used]", s);
+#endif
+                                       continue;
+                               }
+
+                               val = netif_match(&cur_if, machdep_hint);
+#ifdef NETIF_DEBUG
+                               if (netif_debug)
+                                       printf(" [%d -> %d]", s, val);
+#endif
+                               if (val > best_val) {
+                                       best_val = val;
+                                       best_if = cur_if;
+                               }
+                       }
+#ifdef NETIF_DEBUG
+                       if (netif_debug)
+                               printf("\n");
+#endif
+               }
+       }
+
+       if (best_if.nif_driver == NULL)
+               return NULL;
+
+       best_if.nif_driver->
+           netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel);
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("netif_select: %s%d(%d) wins\n",
+                       best_if.nif_driver->netif_bname,
+                       best_if.nif_unit, best_if.nif_sel);
+#endif
+       return &best_if;
+}
+
+int
+netif_probe(struct netif *nif, void *machdep_hint)
+{
+       struct netif_driver *drv = nif->nif_driver;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit);
+#endif
+       return drv->netif_probe(nif, machdep_hint);
+}
+
+void
+netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint)
+{
+       struct netif_driver *drv = nif->nif_driver;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit);
+#endif
+       desc->io_netif = nif;
+#ifdef PARANOID
+       if (drv->netif_init == NULL)
+               panic("%s%d: no netif_init support", drv->netif_bname,
+                   nif->nif_unit);
+#endif
+       drv->netif_init(desc, machdep_hint);
+       (void)memset(drv->netif_ifs[nif->nif_unit].dif_stats, 0,
+           sizeof(struct netif_stats));
+}
+
+void
+netif_detach(struct netif *nif)
+{
+       struct netif_driver *drv = nif->nif_driver;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit);
+#endif
+#ifdef PARANOID
+       if (drv->netif_end == NULL)
+               panic("%s%d: no netif_end support", drv->netif_bname,
+                   nif->nif_unit);
+#endif
+       drv->netif_end(nif);
+}
+
+ssize_t
+netif_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timo)
+{
+       struct netif *nif = desc->io_netif;
+       struct netif_driver *drv = nif->nif_driver;
+       ssize_t rv;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit);
+#endif
+#ifdef PARANOID
+       if (drv->netif_get == NULL)
+               panic("%s%d: no netif_get support", drv->netif_bname,
+                   nif->nif_unit);
+#endif
+       rv = drv->netif_get(desc, pkt, len, timo);
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_get returning %d\n", drv->netif_bname,
+                   nif->nif_unit, (int)rv);
+#endif
+       return rv;
+}
+
+ssize_t
+netif_put(struct iodesc *desc, void *pkt, size_t len)
+{
+       struct netif *nif = desc->io_netif;
+       struct netif_driver *drv = nif->nif_driver;
+       ssize_t rv;
+
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit);
+#endif
+#ifdef PARANOID
+       if (drv->netif_put == NULL)
+               panic("%s%d: no netif_put support", drv->netif_bname,
+                   nif->nif_unit);
+#endif
+       rv = drv->netif_put(desc, pkt, len);
+#ifdef NETIF_DEBUG
+       if (netif_debug)
+               printf("%s%d: netif_put returning %d\n", drv->netif_bname,
+                   nif->nif_unit, (int)rv);
+#endif
+       return rv;
+}
+
+struct iodesc *
+socktodesc(int sock)
+{
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if (sock >= SOPEN_MAX) {
+               errno = EBADF;
+               return NULL;
+       }
+#endif
+       return &sockets[sock];
+}
+
+int
+netif_open(void *machdep_hint)
+{
+       int fd;
+       struct iodesc *s;
+       struct netif *nif;
+
+       /* find a free socket */
+       for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++)
+               if (s->io_netif == (struct netif *)0)
+                       goto fnd;
+       errno = EMFILE;
+       return -1;
+
+fnd:
+       (void)memset(s, 0, sizeof(*s));
+       netif_init();
+       nif = netif_select(machdep_hint);
+       if (!nif)
+               panic("netboot: no interfaces left untried");
+       if (netif_probe(nif, machdep_hint)) {
+               printf("netboot: couldn't probe %s%d\n",
+                   nif->nif_driver->netif_bname, nif->nif_unit);
+               errno = EINVAL;
+               return -1;
+       }
+       netif_attach(nif, s, machdep_hint);
+
+       return fd;
+}
+
+int
+netif_close(int sock)
+{
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if (sock >= SOPEN_MAX) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+       netif_detach(sockets[sock].io_netif);
+       sockets[sock].io_netif = (struct netif *)0;
+
+       return 0;
+}
diff --git a/sys/lib/libsa/netif.h b/sys/lib/libsa/netif.h
new file mode 100644 (file)
index 0000000..446f63a
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: netif.h,v 1.7 2009/01/17 14:00:36 tsutsui Exp $        */
+
+#ifndef __SYS_LIBNETBOOT_NETIF_H
+#define __SYS_LIBNETBOOT_NETIF_H
+
+#include "iodesc.h"
+
+struct netif; /* forward */
+
+struct netif_driver {
+       char    *netif_bname;
+       int     (*netif_match)(struct netif *, void *);
+       int     (*netif_probe)(struct netif *, void *);
+       void    (*netif_init)(struct iodesc *, void *);
+       int     (*netif_get)(struct iodesc *, void *, size_t, saseconds_t);
+       int     (*netif_put)(struct iodesc *, void *, size_t);
+       void    (*netif_end)(struct netif *);
+       struct  netif_dif *netif_ifs;
+       int     netif_nifs;
+};
+
+struct netif_dif {
+       int             dif_unit;
+       int             dif_nsel;
+       struct netif_stats *dif_stats;
+       void            *dif_private;
+       /* the following fields are used internally by the netif layer */
+       u_long          dif_used;
+};
+
+struct netif_stats {
+       int     collisions;
+       int     collision_error;
+       int     missed;
+       int     sent;
+       int     received;
+       int     deferred;
+       int     overflow;
+};
+
+struct netif {
+       struct netif_driver     *nif_driver;
+       int                     nif_unit;
+       int                     nif_sel;
+       void                    *nif_devdata;
+};
+
+extern struct netif_driver     *netif_drivers[];       /* machdep */
+extern int                     n_netif_drivers;
+
+extern int                     netif_debug;
+
+void           netif_init(void);
+struct netif   *netif_select(void *);
+int            netif_probe(struct netif *, void *);
+void           netif_attach(struct netif *, struct iodesc *, void *);
+void           netif_detach(struct netif *);
+
+int            netif_open(void *);
+int            netif_close(int);
+
+#endif /* __SYS_LIBNETBOOT_NETIF_H */
diff --git a/sys/lib/libsa/nfs.c b/sys/lib/libsa/nfs.c
new file mode 100644 (file)
index 0000000..6fadec0
--- /dev/null
@@ -0,0 +1,666 @@
+/*     $NetBSD: nfs.c,v 1.47 2011/12/25 06:09:08 tsutsui Exp $ */
+
+/*-
+ *  Copyright (c) 1993 John Brezak
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XXX Does not currently implement:
+ * XXX
+ * XXX LIBSA_NO_FS_CLOSE
+ * XXX LIBSA_NO_FS_SEEK
+ * XXX LIBSA_NO_FS_WRITE
+ * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?)
+ * XXX LIBSA_FS_SINGLECOMPONENT (does this even make sense?)
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#include "rpcv2.h"
+#include "nfsv2.h"
+
+#include "stand.h"
+#include "net.h"
+#include "nfs.h"
+#include "rpc.h"
+
+/* Define our own NFS attributes */
+struct nfsv2_fattrs {
+       n_long  fa_type;
+       n_long  fa_mode;
+       n_long  fa_nlink;
+       n_long  fa_uid;
+       n_long  fa_gid;
+       n_long  fa_size;
+       n_long  fa_blocksize;
+       n_long  fa_rdev;
+       n_long  fa_blocks;
+       n_long  fa_fsid;
+       n_long  fa_fileid;
+       struct nfsv2_time fa_atime;
+       struct nfsv2_time fa_mtime;
+       struct nfsv2_time fa_ctime;
+};
+
+
+struct nfs_read_args {
+       u_char  fh[NFS_FHSIZE];
+       n_long  off;
+       n_long  len;
+       n_long  xxx;                    /* XXX what's this for? */
+};
+
+/* Data part of nfs rpc reply (also the largest thing we receive) */
+#define NFSREAD_SIZE 1024
+struct nfs_read_repl {
+       n_long  errno;
+       struct  nfsv2_fattrs fa;
+       n_long  count;
+       u_char  data[NFSREAD_SIZE];
+};
+
+#ifndef NFS_NOSYMLINK
+struct nfs_readlnk_repl {
+       n_long  errno;
+       n_long  len;
+       char    path[NFS_MAXPATHLEN];
+};
+#endif
+
+struct nfs_iodesc {
+       struct  iodesc  *iodesc;
+       off_t   off;
+       u_char  fh[NFS_FHSIZE];
+       struct nfsv2_fattrs fa; /* all in network order */
+};
+
+struct nfs_iodesc nfs_root_node;
+
+int    nfs_getrootfh(struct iodesc *, char *, u_char *);
+int    nfs_lookupfh(struct nfs_iodesc *, const char *, int,
+           struct nfs_iodesc *);
+int    nfs_readlink(struct nfs_iodesc *, char *);
+ssize_t        nfs_readdata(struct nfs_iodesc *, off_t, void *, size_t);
+
+/*
+ * Fetch the root file handle (call mount daemon)
+ * On error, return non-zero and set errno.
+ */
+int
+nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp)
+{
+       int len;
+       struct args {
+               n_long  len;
+               char    path[FNAME_SIZE];
+       } *args;
+       struct repl {
+               n_long  errno;
+               u_char  fh[NFS_FHSIZE];
+       } *repl;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct args d;
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct repl d;
+       } rdata;
+       ssize_t cc;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_getrootfh: %s\n", path);
+#endif
+
+       args = &sdata.d;
+       repl = &rdata.d;
+
+       (void)memset(args, 0, sizeof(*args));
+       len = strlen(path);
+       if ((size_t)len > sizeof(args->path))
+               len = sizeof(args->path);
+       args->len = htonl(len);
+       (void)memcpy(args->path, path, len);
+       len = 4 + roundup(len, 4);
+
+       cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
+           args, len, repl, sizeof(*repl));
+       if (cc == -1) {
+               /* errno was set by rpc_call */
+               return -1;
+       }
+       if (cc < 4) {
+               errno = EBADRPC;
+               return -1;
+       }
+       if (repl->errno) {
+               errno = ntohl(repl->errno);
+               return -1;
+       }
+       (void)memcpy(fhp, repl->fh, sizeof(repl->fh));
+       return 0;
+}
+
+/*
+ * Lookup a file.  Store handle and attributes.
+ * Return zero or error number.
+ */
+int
+nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len,
+       struct nfs_iodesc *newfd)
+{
+       int rlen;
+       struct args {
+               u_char  fh[NFS_FHSIZE];
+               n_long  len;
+               char    name[FNAME_SIZE];
+       } *args;
+       struct repl {
+               n_long  errno;
+               u_char  fh[NFS_FHSIZE];
+               struct  nfsv2_fattrs fa;
+       } *repl;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct args d;
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct repl d;
+       } rdata;
+       ssize_t cc;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("lookupfh: called\n");
+#endif
+
+       args = &sdata.d;
+       repl = &rdata.d;
+
+       (void)memset(args, 0, sizeof(*args));
+       (void)memcpy(args->fh, d->fh, sizeof(args->fh));
+       if ((size_t)len > sizeof(args->name))
+               len = sizeof(args->name);
+       (void)memcpy(args->name, name, len);
+       args->len = htonl(len);
+       len = 4 + roundup(len, 4);
+       len += NFS_FHSIZE;
+
+       rlen = sizeof(*repl);
+
+       cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
+           args, len, repl, rlen);
+       if (cc == -1)
+               return errno;           /* XXX - from rpc_call */
+       if (cc < 4)
+               return EIO;
+       if (repl->errno) {
+               /* saerrno.h now matches NFS error numbers. */
+               return ntohl(repl->errno);
+       }
+       (void)memcpy(&newfd->fh, repl->fh, sizeof(newfd->fh));
+       (void)memcpy(&newfd->fa, &repl->fa, sizeof(newfd->fa));
+       return 0;
+}
+
+#ifndef NFS_NOSYMLINK
+/*
+ * Get the destination of a symbolic link.
+ */
+int
+nfs_readlink(struct nfs_iodesc *d, char *buf)
+{
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               u_char fh[NFS_FHSIZE];
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct nfs_readlnk_repl d;
+       } rdata;
+       ssize_t cc;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("readlink: called\n");
+#endif
+
+       (void)memcpy(sdata.fh, d->fh, NFS_FHSIZE);
+       cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
+                     sdata.fh, NFS_FHSIZE,
+                     &rdata.d, sizeof(rdata.d));
+       if (cc == -1)
+               return errno;
+
+       if (cc < 4)
+               return EIO;
+
+       if (rdata.d.errno)
+               return ntohl(rdata.d.errno);
+
+       rdata.d.len = ntohl(rdata.d.len);
+       if (rdata.d.len > NFS_MAXPATHLEN)
+               return ENAMETOOLONG;
+
+       (void)memcpy(buf, rdata.d.path, rdata.d.len);
+       buf[rdata.d.len] = 0;
+       return 0;
+}
+#endif
+
+/*
+ * Read data from a file.
+ * Return transfer count or -1 (and set errno)
+ */
+ssize_t
+nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
+{
+       struct nfs_read_args *args;
+       struct nfs_read_repl *repl;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct nfs_read_args d;
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct nfs_read_repl d;
+       } rdata;
+       ssize_t cc;
+       long x;
+       size_t hlen, rlen;
+
+       args = &sdata.d;
+       repl = &rdata.d;
+
+       (void)memcpy(args->fh, d->fh, NFS_FHSIZE);
+       args->off = htonl((n_long)off);
+       if (len > NFSREAD_SIZE)
+               len = NFSREAD_SIZE;
+       args->len = htonl((n_long)len);
+       args->xxx = htonl((n_long)0);
+       hlen = sizeof(*repl) - NFSREAD_SIZE;
+
+       cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
+           args, sizeof(*args),
+           repl, sizeof(*repl));
+       if (cc == -1) {
+               /* errno was already set by rpc_call */
+               return -1;
+       }
+       if (cc < (ssize_t)hlen) {
+               errno = EBADRPC;
+               return -1;
+       }
+       if (repl->errno) {
+               errno = ntohl(repl->errno);
+               return -1;
+       }
+       rlen = cc - hlen;
+       x = ntohl(repl->count);
+       if (rlen < (size_t)x) {
+               printf("nfsread: short packet, %lu < %ld\n", (u_long) rlen, x);
+               errno = EBADRPC;
+               return -1;
+       }
+       (void)memcpy(addr, repl->data, x);
+       return x;
+}
+
+/*
+ * nfs_mount - mount this nfs filesystem to a host
+ * On error, return non-zero and set errno.
+ */
+int
+nfs_mount(int sock, struct in_addr ip, char *path)
+{
+       struct iodesc *desc;
+       struct nfsv2_fattrs *fa;
+
+       if (!(desc = socktodesc(sock))) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* Bind to a reserved port. */
+       desc->myport = htons(--rpc_port);
+       desc->destip = ip;
+       if (nfs_getrootfh(desc, path, nfs_root_node.fh))
+               return -1;
+       nfs_root_node.iodesc = desc;
+       /* Fake up attributes for the root dir. */
+       fa = &nfs_root_node.fa;
+       fa->fa_type  = htonl(NFDIR);
+       fa->fa_mode  = htonl(0755);
+       fa->fa_nlink = htonl(2);
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_mount: got fh for %s\n", path);
+#endif
+
+       return 0;
+}
+
+/*
+ * Open a file.
+ * return zero or error number
+ */
+__compactcall int
+nfs_open(const char *path, struct open_file *f)
+{
+       struct nfs_iodesc *newfd, *currfd;
+       const char *cp;
+#ifndef NFS_NOSYMLINK
+       const char *ncp;
+       int c;
+       char namebuf[NFS_MAXPATHLEN + 1];
+       char linkbuf[NFS_MAXPATHLEN + 1];
+       int nlinks = 0;
+#endif
+       int error = 0;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_open: %s\n", path);
+#endif
+       if (nfs_root_node.iodesc == NULL) {
+               printf("nfs_open: must mount first.\n");
+               return ENXIO;
+       }
+
+       currfd = &nfs_root_node;
+       newfd = 0;
+
+#ifndef NFS_NOSYMLINK
+       cp = path;
+       while (*cp) {
+               /*
+                * Remove extra separators
+                */
+               while (*cp == '/')
+                       cp++;
+
+               if (*cp == '\0')
+                       break;
+               /*
+                * Check that current node is a directory.
+                */
+               if (currfd->fa.fa_type != htonl(NFDIR)) {
+                       error = ENOTDIR;
+                       goto out;
+               }
+
+               /* allocate file system specific data structure */
+               newfd = alloc(sizeof(*newfd));
+               newfd->iodesc = currfd->iodesc;
+               newfd->off = 0;
+
+               /*
+                * Get next component of path name.
+                */
+               {
+                       int len = 0;
+
+                       ncp = cp;
+                       while ((c = *cp) != '\0' && c != '/') {
+                               if (++len > NFS_MAXNAMLEN) {
+                                       error = ENOENT;
+                                       goto out;
+                               }
+                               cp++;
+                       }
+               }
+
+               /* lookup a file handle */
+               error = nfs_lookupfh(currfd, ncp, cp - ncp, newfd);
+               if (error)
+                       goto out;
+
+               /*
+                * Check for symbolic link
+                */
+               if (newfd->fa.fa_type == htonl(NFLNK)) {
+                       int link_len, len;
+
+                       error = nfs_readlink(newfd, linkbuf);
+                       if (error)
+                               goto out;
+
+                       link_len = strlen(linkbuf);
+                       len = strlen(cp);
+
+                       if (link_len + len > MAXPATHLEN
+                           || ++nlinks > MAXSYMLINKS) {
+                               error = ENOENT;
+                               goto out;
+                       }
+
+                       (void)memcpy(&namebuf[link_len], cp, len + 1);
+                       (void)memcpy(namebuf, linkbuf, link_len);
+
+                       /*
+                        * If absolute pathname, restart at root.
+                        * If relative pathname, restart at parent directory.
+                        */
+                       cp = namebuf;
+                       if (*cp == '/') {
+                               if (currfd != &nfs_root_node)
+                                       dealloc(currfd, sizeof(*currfd));
+                               currfd = &nfs_root_node;
+                       }
+
+                       dealloc(newfd, sizeof(*newfd));
+                       newfd = 0;
+
+                       continue;
+               }
+
+               if (currfd != &nfs_root_node)
+                       dealloc(currfd, sizeof(*currfd));
+               currfd = newfd;
+               newfd = 0;
+       }
+
+       error = 0;
+
+out:
+#else
+       /* allocate file system specific data structure */
+       currfd = alloc(sizeof(*currfd));
+       currfd->iodesc = nfs_root_node.iodesc;
+       currfd->off = 0;
+
+       cp = path;
+       /*
+        * Remove extra separators
+        */
+       while (*cp == '/')
+               cp++;
+
+       /* XXX: Check for empty path here? */
+
+       error = nfs_lookupfh(&nfs_root_node, cp, strlen(cp), currfd);
+#endif
+       if (!error) {
+               f->f_fsdata = (void *)currfd;
+               fsmod = "nfs";
+               return 0;
+       }
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_open: %s lookupfh failed: %s\n",
+                   path, strerror(error));
+#endif
+       if (currfd != &nfs_root_node)
+               dealloc(currfd, sizeof(*currfd));
+       if (newfd)
+               dealloc(newfd, sizeof(*newfd));
+
+       return error;
+}
+
+__compactcall int
+nfs_close(struct open_file *f)
+{
+       struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_close: fp=0x%lx\n", (u_long)fp);
+#endif
+
+       if (fp)
+               dealloc(fp, sizeof(struct nfs_iodesc));
+       f->f_fsdata = (void *)0;
+
+       return 0;
+}
+
+/*
+ * read a portion of a file
+ */
+__compactcall int
+nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+       struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
+       ssize_t cc;
+       char *addr = buf;
+
+#ifdef NFS_DEBUG
+       if (debug)
+               printf("nfs_read: size=%lu off=%d\n", (u_long)size,
+                   (int)fp->off);
+#endif
+       while ((int)size > 0) {
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               cc = nfs_readdata(fp, fp->off, (void *)addr, size);
+               /* XXX maybe should retry on certain errors */
+               if (cc == -1) {
+#ifdef NFS_DEBUG
+                       if (debug)
+                               printf("nfs_read: read: %s\n",
+                                      strerror(errno));
+#endif
+                       return errno;   /* XXX - from nfs_readdata */
+               }
+               if (cc == 0) {
+#ifdef NFS_DEBUG
+                       if (debug)
+                               printf("nfs_read: hit EOF unexpectantly\n");
+#endif
+                       goto ret;
+               }
+               fp->off += cc;
+               addr += cc;
+               size -= cc;
+       }
+ret:
+       if (resid)
+               *resid = size;
+
+       return 0;
+}
+
+/*
+ * Not implemented.
+ */
+__compactcall int
+nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+       return EROFS;
+}
+
+__compactcall off_t
+nfs_seek(struct open_file *f, off_t offset, int where)
+{
+       struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
+       n_long size = ntohl(d->fa.fa_size);
+
+       switch (where) {
+       case SEEK_SET:
+               d->off = offset;
+               break;
+       case SEEK_CUR:
+               d->off += offset;
+               break;
+       case SEEK_END:
+               d->off = size - offset;
+               break;
+       default:
+               return -1;
+       }
+
+       return d->off;
+}
+
+/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
+const int nfs_stat_types[8] = {
+       0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
+
+__compactcall int
+nfs_stat(struct open_file *f, struct stat *sb)
+{
+       struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
+       n_long ftype, mode;
+
+       ftype = ntohl(fp->fa.fa_type);
+       mode  = ntohl(fp->fa.fa_mode);
+       mode |= nfs_stat_types[ftype & 7];
+
+       sb->st_mode  = mode;
+       sb->st_nlink = ntohl(fp->fa.fa_nlink);
+       sb->st_uid   = ntohl(fp->fa.fa_uid);
+       sb->st_gid   = ntohl(fp->fa.fa_gid);
+       sb->st_size  = ntohl(fp->fa.fa_size);
+
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+nfs_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by nfs\n");
+       return;
+}
+#endif
diff --git a/sys/lib/libsa/nfs.h b/sys/lib/libsa/nfs.h
new file mode 100644 (file)
index 0000000..9378126
--- /dev/null
@@ -0,0 +1,33 @@
+/*     $NetBSD: nfs.h,v 1.8 2005/12/11 12:24:46 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+FS_DEF(nfs);
+int nfs_mount(int, struct in_addr, char *);
diff --git a/sys/lib/libsa/nfsv2.h b/sys/lib/libsa/nfsv2.h
new file mode 100644 (file)
index 0000000..c8402a1
--- /dev/null
@@ -0,0 +1,162 @@
+/*     $NetBSD: nfsv2.h,v 1.4 2005/12/11 12:24:46 christos Exp $       */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)nfsv2.h     8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * nfs definitions as per the version 2 specs
+ */
+
+/*
+ * Constants as defined in the Sun NFS Version 2 spec.
+ * "NFS: Network File System Protocol Specification" RFC1094
+ */
+
+#define NFS_PORT       2049
+#define        NFS_PROG        100003
+#define NFS_VER2       2
+#define        NFS_MAXDGRAMDATA 8192
+#define        NFS_MAXDATA     32768
+#define        NFS_MAXPATHLEN  1024
+#define        NFS_MAXNAMLEN   255
+#define        NFS_FHSIZE      32
+#define        NFS_MAXPKTHDR   404
+#define NFS_MAXPACKET  (NFS_MAXPKTHDR+NFS_MAXDATA)
+#define        NFS_MINPACKET   20
+#define        NFS_FABLKSIZE   512     /* Size in bytes of a block wrt fa_blocks */
+
+/* Stat numbers for rpc returns */
+#define        NFS_OK          0
+#define        NFSERR_PERM     1
+#define        NFSERR_NOENT    2
+#define        NFSERR_IO       5
+#define        NFSERR_NXIO     6
+#define        NFSERR_ACCES    13
+#define        NFSERR_EXIST    17
+#define        NFSERR_NODEV    19
+#define        NFSERR_NOTDIR   20
+#define        NFSERR_ISDIR    21
+#define        NFSERR_FBIG     27
+#define        NFSERR_NOSPC    28
+#define        NFSERR_ROFS     30
+#define        NFSERR_NAMETOL  63
+#define        NFSERR_NOTEMPTY 66
+#define        NFSERR_DQUOT    69
+#define        NFSERR_STALE    70
+#define        NFSERR_WFLUSH   99
+
+/* Sizes in bytes of various nfs rpc components */
+#define        NFSX_FH         32
+#define        NFSX_UNSIGNED   4
+#define        NFSX_FATTR      68
+#define        NFSX_SATTR      32
+#define NFSX_STATFS    20
+#define        NFSX_COOKIE     4
+
+/* nfs rpc procedure numbers */
+#define        NFSPROC_NULL            0
+#define        NFSPROC_GETATTR         1
+#define        NFSPROC_SETATTR         2
+#define        NFSPROC_NOOP            3
+#define        NFSPROC_ROOT            NFSPROC_NOOP    /* Obsolete */
+#define        NFSPROC_LOOKUP          4
+#define        NFSPROC_READLINK        5
+#define        NFSPROC_READ            6
+#define        NFSPROC_WRITECACHE      NFSPROC_NOOP    /* Obsolete */
+#define        NFSPROC_WRITE           8
+#define        NFSPROC_CREATE          9
+#define        NFSPROC_REMOVE          10
+#define        NFSPROC_RENAME          11
+#define        NFSPROC_LINK            12
+#define        NFSPROC_SYMLINK         13
+#define        NFSPROC_MKDIR           14
+#define        NFSPROC_RMDIR           15
+#define        NFSPROC_READDIR         16
+#define        NFSPROC_STATFS          17
+
+#define        NFS_NPROCS              18
+
+
+/* File types */
+typedef enum {
+       NFNON=0,
+       NFREG=1,
+       NFDIR=2,
+       NFBLK=3,
+       NFCHR=4,
+       NFLNK=5
+} nfstype;
+
+/* Structs for common parts of the rpc's */
+struct nfsv2_time {
+       n_long  nfs_sec;
+       n_long  nfs_usec;
+};
+
+/*
+ * File attributes and setable attributes.
+ */
+struct nfsv2_fattr {
+       n_long  fa_type;
+       n_long  fa_mode;
+       n_long  fa_nlink;
+       n_long  fa_uid;
+       n_long  fa_gid;
+       n_long  fa_size;
+       n_long  fa_blocksize;
+       n_long  fa_rdev;
+       n_long  fa_blocks;
+       n_long  fa_fsid;
+       n_long  fa_fileid;
+       struct nfsv2_time fa_atime;
+       struct nfsv2_time fa_mtime;
+       struct nfsv2_time fa_ctime;
+};
+
+struct nfsv2_sattr {
+       n_long  sa_mode;
+       n_long  sa_uid;
+       n_long  sa_gid;
+       n_long  sa_size;
+       struct nfsv2_time sa_atime;
+       struct nfsv2_time sa_mtime;
+};
+
+struct nfsv2_statfs {
+       n_long  sf_tsize;
+       n_long  sf_bsize;
+       n_long  sf_blocks;
+       n_long  sf_bfree;
+       n_long  sf_bavail;
+};
diff --git a/sys/lib/libsa/nullfs.c b/sys/lib/libsa/nullfs.c
new file mode 100644 (file)
index 0000000..558de60
--- /dev/null
@@ -0,0 +1,124 @@
+/*     $NetBSD: nullfs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $      */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)open.c      8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+/*
+ * Null filesystem
+ */
+
+__compactcall int
+null_open(const char *path, struct open_file *f)
+{
+
+       return EIO;
+}
+
+#ifndef LIBSA_NO_FS_CLOSE
+__compactcall int
+null_close(struct open_file *f)
+{
+
+       return 0;
+}
+#endif
+
+__compactcall int
+null_read(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+
+       return EIO;
+}
+
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+null_write(struct open_file *f, void *buf, size_t size, size_t *resid)
+{
+
+       return EIO;
+}
+#endif
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+null_seek(struct open_file *f, off_t offset, int where)
+{
+
+       return (off_t)-1;
+}
+#endif
+
+__compactcall int
+null_stat(struct open_file *f, struct stat *sb)
+{
+
+       return EIO;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+null_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by nullfs\n");
+       return;
+}
+#endif
diff --git a/sys/lib/libsa/open.c b/sys/lib/libsa/open.c
new file mode 100644 (file)
index 0000000..c29c95a
--- /dev/null
@@ -0,0 +1,157 @@
+/*     $NetBSD: open.c,v 1.26 2007/11/24 13:20:56 isaki Exp $  */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)open.c      8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include "stand.h"
+
+/*
+ *     File primitives proper
+ */
+
+#ifdef HELLO_CTAGS
+oopen(){}
+#endif
+
+int
+#ifndef __INTERNAL_LIBSA_CREAD
+open(const char *fname, int mode)
+#else
+oopen(const char *fname, int mode)
+#endif
+{
+       struct open_file *f;
+       int fd, error;
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+       int i, besterror;
+#endif
+       char *file;
+
+       /* find a free file descriptor */
+       for (fd = 0, f = files; fd < SOPEN_MAX; fd++, f++)
+               if (f->f_flags == 0)
+                       goto fnd;
+       errno = EMFILE;
+       return -1;
+fnd:
+       /*
+        * Try to open the device.
+        * Convert open mode (0,1,2) to F_READ, F_WRITE.
+        */
+       f->f_flags = mode + 1;
+#if !defined(LIBSA_SINGLE_DEVICE)
+       f->f_dev = (struct devsw *)0;
+#endif
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+       f->f_ops = (struct fs_ops *)0;
+#endif
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       f->f_offset = 0;
+#endif
+       file = (char *)0;
+       error = devopen(f, fname, &file);
+       if (error
+#if !defined(LIBSA_SINGLE_DEVICE)
+           || (((f->f_flags & F_NODEV) == 0) &&
+               f->f_dev == (struct devsw *)0)
+#endif
+           )
+               goto err;
+
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       /* see if we opened a raw device; otherwise, 'file' is the file name. */
+       if (file == (char *)0 || *file == '\0') {
+               f->f_flags |= F_RAW;
+               return fd;
+       }
+#endif
+
+       /* pass file name to the different filesystem open routines */
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+       besterror = ENOENT;
+       for (i = 0; i < nfsys; i++) {
+               error = FS_OPEN(&file_system[i])(file, f);
+               if (error == 0) {
+                       f->f_ops = &file_system[i];
+                       return fd;
+               }
+               if (error != EINVAL)
+                       besterror = error;
+       }
+       error = besterror;
+#else
+       error = FS_OPEN(&file_system[i])(file, f);
+       if (error == 0)
+               return fd;
+       if (error == EINVAL)
+               error = ENOENT;
+#endif
+
+       if ((f->f_flags & F_NODEV) == 0) {
+#if !defined(LIBSA_SINGLE_DEVICE)
+               if (DEV_CLOSE(f->f_dev) != NULL)
+#endif
+                       (void)DEV_CLOSE(f->f_dev)(f);
+       }
+err:
+       f->f_flags = 0;
+       errno = error;
+       return -1;
+}
diff --git a/sys/lib/libsa/panic.c b/sys/lib/libsa/panic.c
new file mode 100644 (file)
index 0000000..c91adfc
--- /dev/null
@@ -0,0 +1,53 @@
+/*     $NetBSD: panic.c,v 1.7 2011/07/17 20:54:52 joerg Exp $  */
+
+/*-
+ *  Copyright (c) 1993 John Brezak
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/stdarg.h>
+
+#include "stand.h"
+
+__dead void
+panic(const char *fmt, ...)
+{
+       va_list ap;
+#ifndef LIBSA_NO_FS_CLOSE
+       static int paniced;
+
+       if (!paniced) {
+               paniced = 1;
+               closeall();
+       }
+#endif
+
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       printf("\n");
+       va_end(ap);
+       _rtt();
+       /*NOTREACHED*/
+}
diff --git a/sys/lib/libsa/printf.c b/sys/lib/libsa/printf.c
new file mode 100644 (file)
index 0000000..ba3dc4f
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: printf.c,v 1.18 2011/07/17 20:54:52 joerg Exp $        */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stdarg.h>
+
+#include "stand.h"
+
+void
+printf(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+}
diff --git a/sys/lib/libsa/qsort.c b/sys/lib/libsa/qsort.c
new file mode 100644 (file)
index 0000000..206be0b
--- /dev/null
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/libkern/qsort.c,v 1.12 2002/11/09 12:55:06 alfred Exp $
+ * $NetBSD: qsort.c,v 1.4 2007/11/24 13:20:56 isaki Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+typedef int             cmp_t(const void *, const void *);
+static inline char     *med3(char *, char *, char *, cmp_t *);
+static inline void      swapfunc(char *, char *, int, int);
+
+#define min(a, b)      (a) < (b) ? (a) : (b)
+
+void qsort(void *a, size_t n, size_t es, cmp_t *cmp);
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) {              \
+       long i = (n) / sizeof (TYPE);                   \
+       register TYPE *pi = (TYPE *)(parmi);            \
+       register TYPE *pj = (TYPE *)(parmj);            \
+       do {                                            \
+               register TYPE   t = *pi;                \
+               *pi++ = *pj;                            \
+               *pj++ = t;                              \
+       } while (--i > 0);                              \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+       es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc(char *a, char *b, int n, int swaptype)
+{
+       if(swaptype <= 1)
+               swapcode(long, a, b, n)
+       else
+               swapcode(char, a, b, n)
+}
+
+#define swap(a, b)                                     \
+       if (swaptype == 0) {                            \
+               long t = *(long *)(a);                  \
+               *(long *)(a) = *(long *)(b);            \
+               *(long *)(b) = t;                       \
+       } else                                          \
+               swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n)       if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+static inline char *
+med3(char *a, char *b, char *c, cmp_t *cmp)
+{
+       return cmp(a, b) < 0 ?
+              (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
+             :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+}
+
+void
+qsort(void *a, size_t n, size_t es, cmp_t *cmp)
+{
+       char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+       int d, r, swaptype, swap_cnt;
+
+loop:
+       SWAPINIT(a, es);
+       swap_cnt = 0;
+       if (n < 7) {
+               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+                       for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
+                            pl -= es)
+                               swap(pl, pl - es);
+               return;
+       }
+       pm = (char *)a + (n / 2) * es;
+       if (n > 7) {
+               pl = a;
+               pn = (char *)a + (n - 1) * es;
+               if (n > 40) {
+                       d = (n / 8) * es;
+                       pl = med3(pl, pl + d, pl + 2 * d, cmp);
+                       pm = med3(pm - d, pm, pm + d, cmp);
+                       pn = med3(pn - 2 * d, pn - d, pn, cmp);
+               }
+               pm = med3(pl, pm, pn, cmp);
+       }
+       swap(a, pm);
+       pa = pb = (char *)a + es;
+
+       pc = pd = (char *)a + (n - 1) * es;
+       for (;;) {
+               while (pb <= pc && (r = cmp(pb, a)) <= 0) {
+                       if (r == 0) {
+                               swap_cnt = 1;
+                               swap(pa, pb);
+                               pa += es;
+                       }
+                       pb += es;
+               }
+               while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+                       if (r == 0) {
+                               swap_cnt = 1;
+                               swap(pc, pd);
+                               pd -= es;
+                       }
+                       pc -= es;
+               }
+               if (pb > pc)
+                       break;
+               swap(pb, pc);
+               swap_cnt = 1;
+               pb += es;
+               pc -= es;
+       }
+       if (swap_cnt == 0) {  /* Switch to insertion sort */
+               for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+                       for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0;
+                            pl -= es)
+                               swap(pl, pl - es);
+               return;
+       }
+
+       pn = (char *)a + n * es;
+       r = min(pa - (char *)a, pb - pa);
+       vecswap(a, pb - r, r);
+       r = min(pd - pc, pn - pd - es);
+       vecswap(pb, pn - r, r);
+       if ((r = pb - pa) > es)
+               qsort(a, r / es, es, cmp);
+       if ((r = pd - pc) > es) {
+               /* Iterate rather than recurse to save stack space */
+               a = pn - r;
+               n = r / es;
+               goto loop;
+       }
+/*             qsort(pn - r, r / es, es, cmp);*/
+}
diff --git a/sys/lib/libsa/rarp.c b/sys/lib/libsa/rarp.c
new file mode 100644 (file)
index 0000000..1e0a717
--- /dev/null
@@ -0,0 +1,240 @@
+/*     $NetBSD: rarp.c,v 1.31 2011/05/11 16:23:40 zoltan Exp $ */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <netinet/in.h>
+
+#include <netinet/in_systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#include "net.h"
+
+
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description.  Structure below is adapted
+ * to resolving internet addresses.  Field names used correspond to
+ * RFC 826.
+ */
+struct ether_arp {
+       struct   arphdr ea_hdr;                 /* fixed-size header */
+       u_int8_t arp_sha[ETHER_ADDR_LEN];       /* sender hardware address */
+       u_int8_t arp_spa[4];                    /* sender protocol address */
+       u_int8_t arp_tha[ETHER_ADDR_LEN];       /* target hardware address */
+       u_int8_t arp_tpa[4];                    /* target protocol address */
+};
+#define        arp_hrd ea_hdr.ar_hrd
+#define        arp_pro ea_hdr.ar_pro
+#define        arp_hln ea_hdr.ar_hln
+#define        arp_pln ea_hdr.ar_pln
+#define        arp_op  ea_hdr.ar_op
+
+static ssize_t rarpsend(struct iodesc *, void *, size_t);
+static ssize_t rarprecv(struct iodesc *, void *, size_t, saseconds_t);
+
+/*
+ * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
+ */
+int
+rarp_getipaddress(int sock)
+{
+       struct iodesc *d;
+       struct ether_arp *ap;
+       struct {
+               u_char header[ETHERNET_HEADER_SIZE];
+               struct {
+                       struct ether_arp arp;
+                       u_char pad[18];         /* 60 - sizeof(arp) */
+               } data;
+       } wbuf;
+       struct {
+               u_char header[ETHERNET_HEADER_SIZE];
+               struct {
+                       struct ether_arp arp;
+                       u_char pad[24];         /* extra space */
+               } data;
+       } rbuf;
+
+#ifdef RARP_DEBUG
+       if (debug)
+               printf("rarp: socket=%d\n", sock);
+#endif
+       if (!(d = socktodesc(sock))) {
+               printf("rarp: bad socket. %d\n", sock);
+               return -1;
+       }
+#ifdef RARP_DEBUG
+       if (debug)
+               printf("rarp: d=%lx\n", (u_long)d);
+#endif
+
+       (void)memset(&wbuf.data, 0, sizeof(wbuf.data));
+       ap = &wbuf.data.arp;
+       ap->arp_hrd = htons(ARPHRD_ETHER);
+       ap->arp_pro = htons(ETHERTYPE_IP);
+       ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
+       ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
+       ap->arp_op = htons(ARPOP_REVREQUEST);
+       (void)memcpy(ap->arp_sha, d->myea, 6);
+       (void)memcpy(ap->arp_tha, d->myea, 6);
+
+       if (sendrecv(d,
+           rarpsend, &wbuf.data, sizeof(wbuf.data),
+           rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
+       {
+               printf("No response for RARP request\n");
+               return -1;
+       }
+
+       ap = &rbuf.data.arp;
+       (void)memcpy(&myip, ap->arp_tpa, sizeof(myip));
+#if 0
+       /* XXX - Can NOT assume this is our root server! */
+       (void)memcpy(&rootip, ap->arp_spa, sizeof(rootip));
+#endif
+
+       /* Compute our "natural" netmask. */
+       if (IN_CLASSA(myip.s_addr))
+               netmask = IN_CLASSA_NET;
+       else if (IN_CLASSB(myip.s_addr))
+               netmask = IN_CLASSB_NET;
+       else
+               netmask = IN_CLASSC_NET;
+
+       d->myip = myip;
+       return 0;
+}
+
+/*
+ * Broadcast a RARP request (i.e. who knows who I am)
+ */
+static ssize_t
+rarpsend(struct iodesc *d, void *pkt, size_t len)
+{
+
+#ifdef RARP_DEBUG
+       if (debug)
+               printf("rarpsend: called\n");
+#endif
+
+       return sendether(d, pkt, len, bcea, ETHERTYPE_REVARP);
+}
+
+/*
+ * Returns 0 if this is the packet we're waiting for
+ * else -1 (and errno == 0)
+ */
+static ssize_t
+rarprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       ssize_t n;
+       struct ether_arp *ap;
+       u_int16_t etype;        /* host order */
+
+#ifdef RARP_DEBUG
+       if (debug)
+               printf("rarprecv: ");
+#endif
+
+       n = readether(d, pkt, len, tleft, &etype);
+       errno = 0;      /* XXX */
+       if (n == -1 || (size_t)n < sizeof(struct ether_arp)) {
+#ifdef RARP_DEBUG
+               if (debug)
+                       printf("bad len=%d\n", (int)n);
+#endif
+               return -1;
+       }
+
+       if (etype != ETHERTYPE_REVARP) {
+#ifdef RARP_DEBUG
+               if (debug)
+                       printf("bad type=0x%x\n", etype);
+#endif
+               return -1;
+       }
+
+       ap = (struct ether_arp *)pkt;
+       if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
+           ap->arp_pro != htons(ETHERTYPE_IP) ||
+           ap->arp_hln != sizeof(ap->arp_sha) ||
+           ap->arp_pln != sizeof(ap->arp_spa) )
+       {
+#ifdef RARP_DEBUG
+               if (debug)
+                       printf("bad hrd/pro/hln/pln\n");
+#endif
+               return -1;
+       }
+
+       if (ap->arp_op != htons(ARPOP_REVREPLY)) {
+#ifdef RARP_DEBUG
+               if (debug)
+                       printf("bad op=0x%x\n", ntohs(ap->arp_op));
+#endif
+               return -1;
+       }
+
+       /* Is the reply for our Ethernet address? */
+       if (memcmp(ap->arp_tha, d->myea, 6)) {
+#ifdef RARP_DEBUG
+               if (debug)
+                       printf("unwanted address\n");
+#endif
+               return -1;
+       }
+
+       /* We have our answer. */
+#ifdef RARP_DEBUG
+       if (debug)
+               printf("got it\n");
+#endif
+       return n;
+}
diff --git a/sys/lib/libsa/read.c b/sys/lib/libsa/read.c
new file mode 100644 (file)
index 0000000..1e4752c
--- /dev/null
@@ -0,0 +1,99 @@
+/*     $NetBSD: read.c,v 1.15 2007/12/02 04:59:26 tsutsui Exp $        */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)read.c      8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include "stand.h"
+
+ssize_t
+#ifndef __INTERNAL_LIBSA_CREAD
+read(int fd, void *dest, size_t bcount)
+#else
+oread(int fd, void *dest, size_t bcount)
+#endif
+{
+       struct open_file *f = &files[fd];
+       size_t resid;
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       if (f->f_flags & F_RAW) {
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               errno = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                       btodb(f->f_offset), bcount, dest, &resid);
+               if (errno)
+                       return -1;
+               f->f_offset += resid;
+               return resid;
+       }
+#endif
+       resid = bcount;
+       if ((errno = FS_READ(f->f_ops)(f, dest, bcount, &resid)))
+               return -1;
+       return (ssize_t)(bcount - resid);
+}
diff --git a/sys/lib/libsa/rpc.c b/sys/lib/libsa/rpc.c
new file mode 100644 (file)
index 0000000..b0ec168
--- /dev/null
@@ -0,0 +1,441 @@
+/*     $NetBSD: rpc.c,v 1.29 2009/01/17 14:00:36 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp  (LBL)
+ */
+
+/*
+ * RPC functions used by NFS and bootparams.
+ * Note that bootparams requires the ability to find out the
+ * address of the server from which its response has come.
+ * This is supported by keeping the IP/UDP headers in the
+ * buffer space provided by the caller.  (See rpc_fromaddr)
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#include "stand.h"
+#else
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#endif
+
+#include "rpcv2.h"
+
+#include "net.h"
+#include "rpc.h"
+
+struct auth_info {
+       int32_t         authtype;       /* auth type */
+       u_int32_t       authlen;        /* auth length */
+};
+
+struct auth_unix {
+       int32_t   ua_time;
+       int32_t   ua_hostname;  /* null */
+       int32_t   ua_uid;
+       int32_t   ua_gid;
+       int32_t   ua_gidlist;   /* null */
+};
+
+struct rpc_call {
+       u_int32_t       rp_xid;         /* request transaction id */
+       int32_t         rp_direction;   /* call direction (0) */
+       u_int32_t       rp_rpcvers;     /* rpc version (2) */
+       u_int32_t       rp_prog;        /* program */
+       u_int32_t       rp_vers;        /* version */
+       u_int32_t       rp_proc;        /* procedure */
+};
+
+struct rpc_reply {
+       u_int32_t       rp_xid;         /* request transaction id */
+       int32_t         rp_direction;   /* call direction (1) */
+       int32_t         rp_astatus;     /* accept status (0: accepted) */
+       union {
+               u_int32_t       rpu_errno;
+               struct {
+                       struct auth_info rok_auth;
+                       u_int32_t       rok_status;
+               } rpu_rok;
+       } rp_u;
+};
+
+/* Local forwards */
+static ssize_t recvrpc(struct iodesc *, void *, size_t, saseconds_t);
+
+int rpc_xid;
+int rpc_port = 0x400;  /* predecrement */
+
+/*
+ * Make a rpc call; return length of answer
+ * Note: Caller must leave room for headers.
+ */
+ssize_t
+rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc,
+       void *sdata, size_t slen, void *rdata, size_t rlen)
+{
+       ssize_t cc;
+       struct auth_info *auth;
+       struct rpc_call *call;
+       struct rpc_reply *reply;
+       char *send_head, *send_tail;
+       char *recv_head, *recv_tail;
+       n_long x;
+       int port;       /* host order */
+
+#ifdef RPC_DEBUG
+       if (debug)
+               printf("rpc_call: prog=0x%x vers=%d proc=%d\n",
+                   prog, vers, proc);
+#endif
+
+       port = rpc_getport(d, prog, vers);
+       if (port == -1)
+               return -1;
+
+       d->destport = htons(port);
+
+       /*
+        * Prepend authorization stuff and headers.
+        * Note, must prepend things in reverse order.
+        */
+       send_head = sdata;
+       send_tail = (char *)sdata + slen;
+
+       /* Auth verifier is always auth_null */
+       send_head -= sizeof(*auth);
+       auth = (struct auth_info *)send_head;
+       auth->authtype = htonl(RPCAUTH_NULL);
+       auth->authlen = 0;
+
+#if 1
+       /* Auth credentials: always auth unix (as root) */
+       send_head -= sizeof(struct auth_unix);
+       (void)memset(send_head, 0, sizeof(struct auth_unix));
+       send_head -= sizeof(*auth);
+       auth = (struct auth_info *)send_head;
+       auth->authtype = htonl(RPCAUTH_UNIX);
+       auth->authlen = htonl(sizeof(struct auth_unix));
+#else
+       /* Auth credentials: always auth_null (XXX OK?) */
+       send_head -= sizeof(*auth);
+       auth = send_head;
+       auth->authtype = htonl(RPCAUTH_NULL);
+       auth->authlen = 0;
+#endif
+
+       /* RPC call structure. */
+       send_head -= sizeof(*call);
+       call = (struct rpc_call *)send_head;
+       rpc_xid++;
+       call->rp_xid       = htonl(rpc_xid);
+       call->rp_direction = htonl(RPC_CALL);
+       call->rp_rpcvers   = htonl(RPC_VER2);
+       call->rp_prog = htonl(prog);
+       call->rp_vers = htonl(vers);
+       call->rp_proc = htonl(proc);
+
+       /* Make room for the rpc_reply header. */
+       recv_head = rdata;
+       recv_tail = (char *)rdata + rlen;
+       recv_head -= sizeof(*reply);
+
+       cc = sendrecv(d,
+           sendudp, send_head, send_tail - send_head,
+           recvrpc, recv_head, recv_tail - recv_head);
+
+#ifdef RPC_DEBUG
+       if (debug)
+               printf("callrpc: cc=%ld rlen=%lu\n", (long)cc, (u_long)rlen);
+#endif
+       if (cc == -1)
+               return -1;
+
+       if ((size_t)cc <= sizeof(*reply)) {
+               errno = EBADRPC;
+               return -1;
+       }
+
+       recv_tail = recv_head + cc;
+
+       /*
+        * Check the RPC reply status.
+        * The xid, dir, astatus were already checked.
+        */
+       reply = (struct rpc_reply *)recv_head;
+       auth = &reply->rp_u.rpu_rok.rok_auth;
+       x = ntohl(auth->authlen);
+       if (x != 0) {
+#ifdef RPC_DEBUG
+               if (debug)
+                       printf("callrpc: reply auth != NULL\n");
+#endif
+               errno = EBADRPC;
+               return -1;
+       }
+       x = ntohl(reply->rp_u.rpu_rok.rok_status);
+       if (x != 0) {
+               printf("callrpc: error = %d\n", x);
+               errno = EBADRPC;
+               return -1;
+       }
+       recv_head += sizeof(*reply);
+
+       return (ssize_t)(recv_tail - recv_head);
+}
+
+/*
+ * Returns true if packet is the one we're waiting for.
+ * This just checks the XID, direction, acceptance.
+ * Remaining checks are done by callrpc
+ */
+static ssize_t
+recvrpc(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       struct rpc_reply *reply;
+       ssize_t n;
+       int     x;
+
+       errno = 0;
+#ifdef RPC_DEBUG
+       if (debug)
+               printf("recvrpc: called len=%lu\n", (u_long)len);
+#endif
+
+       n = readudp(d, pkt, len, tleft);
+       if (n <= (4 * 4))
+               return -1;
+
+       reply = (struct rpc_reply *)pkt;
+
+       x = ntohl(reply->rp_xid);
+       if (x != rpc_xid) {
+#ifdef RPC_DEBUG
+               if (debug)
+                       printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid);
+#endif
+               return -1;
+       }
+
+       x = ntohl(reply->rp_direction);
+       if (x != RPC_REPLY) {
+#ifdef RPC_DEBUG
+               if (debug)
+                       printf("recvrpc: rp_direction %d != REPLY\n", x);
+#endif
+               return -1;
+       }
+
+       x = ntohl(reply->rp_astatus);
+       if (x != RPC_MSGACCEPTED) {
+               errno = ntohl(reply->rp_u.rpu_errno);
+               printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno);
+               return -1;
+       }
+
+       /* Return data count (thus indicating success) */
+       return n;
+}
+
+/*
+ * Given a pointer to a reply just received,
+ * dig out the IP address/port from the headers.
+ */
+void
+rpc_fromaddr(void *pkt, struct in_addr *addr, u_short *port)
+{
+       struct hackhdr {
+               /* Tail of IP header: just IP addresses */
+               n_long ip_src;
+               n_long ip_dst;
+               /* UDP header: */
+               u_int16_t uh_sport;             /* source port */
+               u_int16_t uh_dport;             /* destination port */
+               int16_t   uh_ulen;              /* udp length */
+               u_int16_t uh_sum;               /* udp checksum */
+               /* RPC reply header: */
+               struct rpc_reply rpc;
+       } *hhdr;
+
+       hhdr = ((struct hackhdr *)pkt) - 1;
+       addr->s_addr = hhdr->ip_src;
+       *port = hhdr->uh_sport;
+}
+
+#ifdef NO_PMAP_CACHE
+#define rpc_pmap_getcache(addr, prog, vers) (-1)
+#define rpc_pmap_putcache(addr, prog, vers, port)
+#else
+
+/*
+ * RPC Portmapper cache
+ */
+#define PMAP_NUM 8                     /* need at most 5 pmap entries */
+
+int rpc_pmap_num;
+struct pmap_list {
+       struct in_addr  addr;   /* server, net order */
+       u_int   prog;           /* host order */
+       u_int   vers;           /* host order */
+       int     port;           /* host order */
+} rpc_pmap_list[PMAP_NUM];
+
+/*
+ * return port number in host order, or -1.
+ * arguments are:
+ *  addr .. server, net order.
+ *  prog .. host order.
+ *  vers .. host order.
+ */
+int
+rpc_pmap_getcache(struct in_addr addr, u_int prog, u_int vers)
+{
+       struct pmap_list *pl;
+
+       for (pl = rpc_pmap_list; pl < &rpc_pmap_list[rpc_pmap_num]; pl++) {
+               if (pl->addr.s_addr == addr.s_addr &&
+                       pl->prog == prog && pl->vers == vers )
+               {
+                       return pl->port;
+               }
+       }
+       return -1;
+}
+
+/*
+ * arguments are:
+ *  addr .. server, net order.
+ *  prog .. host order.
+ *  vers .. host order.
+ *  port .. host order.
+ */
+void
+rpc_pmap_putcache(struct in_addr addr, u_int prog, u_int vers, int port)
+{
+       struct pmap_list *pl;
+
+       /* Don't overflow cache... */
+       if (rpc_pmap_num >= PMAP_NUM) {
+               /* ... just re-use the last entry. */
+               rpc_pmap_num = PMAP_NUM - 1;
+#ifdef RPC_DEBUG
+               printf("rpc_pmap_putcache: cache overflow\n");
+#endif
+       }
+
+       pl = &rpc_pmap_list[rpc_pmap_num];
+       rpc_pmap_num++;
+
+       /* Cache answer */
+       pl->addr = addr;
+       pl->prog = prog;
+       pl->vers = vers;
+       pl->port = port;
+}
+#endif
+
+/*
+ * Request a port number from the port mapper.
+ * Returns the port in host order.
+ * prog and vers are host order.
+ */
+int
+rpc_getport(struct iodesc *d, n_long prog, n_long vers)
+{
+       struct args {
+               n_long  prog;           /* call program */
+               n_long  vers;           /* call version */
+               n_long  proto;          /* call protocol */
+               n_long  port;           /* call port (unused) */
+       } *args;
+       struct res {
+               n_long port;
+       } *res;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct args d;
+       } sdata;
+       struct {
+               n_long  h[RPC_HEADER_WORDS];
+               struct res d;
+               n_long  pad;
+       } rdata;
+       ssize_t cc;
+       int port;
+
+#ifdef RPC_DEBUG
+       if (debug)
+               printf("getport: prog=0x%x vers=%d\n", prog, vers);
+#endif
+
+       /* This one is fixed forever. */
+       if (prog == PMAPPROG)
+               return PMAPPORT;
+
+       /* Try for cached answer first */
+       port = rpc_pmap_getcache(d->destip, prog, vers);
+       if (port != -1)
+               return port;
+
+       args = &sdata.d;
+       args->prog = htonl(prog);
+       args->vers = htonl(vers);
+       args->proto = htonl(IPPROTO_UDP);
+       args->port = 0;
+       res = &rdata.d;
+
+       cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
+               args, sizeof(*args), res, sizeof(*res));
+       if ((size_t)cc < sizeof(*res)) {
+               printf("getport: %s", strerror(errno));
+               errno = EBADRPC;
+               return -1;
+       }
+       port = (int)ntohl(res->port);
+
+       rpc_pmap_putcache(d->destip, prog, vers, port);
+
+       return port;
+}
diff --git a/sys/lib/libsa/rpc.h b/sys/lib/libsa/rpc.h
new file mode 100644 (file)
index 0000000..756cdc8
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: rpc.h,v 1.11 2009/01/17 14:00:36 tsutsui Exp $ */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* XXX defines we can't easily get from system includes */
+#define        PMAPPORT                111
+#define        PMAPPROG                100000
+#define        PMAPVERS                2
+#define        PMAPPROC_NULL           0
+#define        PMAPPROC_SET            1
+#define        PMAPPROC_UNSET          2
+#define        PMAPPROC_GETPORT        3
+#define        PMAPPROC_DUMP           4
+#define        PMAPPROC_CALLIT         5
+
+/* RPC functions: */
+ssize_t        rpc_call(struct iodesc *, n_long, n_long, n_long, void *, size_t,
+    void *, size_t);
+void   rpc_fromaddr(void *, struct in_addr *, u_short *);
+int    rpc_pmap_getcache(struct in_addr, u_int, u_int);
+void   rpc_pmap_putcache(struct in_addr, u_int, u_int, int);
+int    rpc_getport(struct iodesc *, n_long, n_long);
+
+extern int rpc_port;   /* decrement before bind */
+
+/*
+ * How much space to leave in front of RPC requests.
+ * In 32-bit words (alignment) we have:
+ * 12: Ether + IP + UDP + padding
+ *  6: RPC call header
+ *  7: Auth UNIX
+ *  2: Auth NULL
+ */
+#define        RPC_HEADER_WORDS 28
diff --git a/sys/lib/libsa/rpcv2.h b/sys/lib/libsa/rpcv2.h
new file mode 100644 (file)
index 0000000..43fd4bf
--- /dev/null
@@ -0,0 +1,85 @@
+/*     $NetBSD: rpcv2.h,v 1.3 2005/12/11 12:24:46 christos Exp $       */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)rpcv2.h     8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Definitions for Sun RPC Version 2, from
+ * "RPC: Remote Procedure Call Protocol Specification" RFC1057
+ */
+
+/* Version # */
+#define        RPC_VER2        2
+
+/* Authentication */
+#define        RPCAUTH_NULL    0
+#define        RPCAUTH_UNIX    1
+#define        RPCAUTH_SHORT   2
+#define        RPCAUTH_MAXSIZ  400
+#define        RPCAUTH_UNIXGIDS 16
+
+/* Rpc Constants */
+#define        RPC_CALL        0
+#define        RPC_REPLY       1
+#define        RPC_MSGACCEPTED 0
+#define        RPC_MSGDENIED   1
+#define        RPC_PROGUNAVAIL 1
+#define        RPC_PROGMISMATCH        2
+#define        RPC_PROCUNAVAIL 3
+#define        RPC_GARBAGE     4               /* I like this one */
+#define        RPC_MISMATCH    0
+#define        RPC_AUTHERR     1
+
+/* Authentication failures */
+#define        AUTH_BADCRED    1
+#define        AUTH_REJECTCRED 2
+#define        AUTH_BADVERF    3
+#define        AUTH_REJECTVERF 4
+#define        AUTH_TOOWEAK    5               /* Give em wheaties */
+
+/* Sizes of rpc header parts */
+#define        RPC_SIZ         24
+#define        RPC_REPLYSIZ    28
+
+/* RPC Prog definitions */
+#define        RPCPROG_MNT     100005
+#define        RPCMNT_VER1     1
+#define        RPCMNT_MOUNT    1
+#define        RPCMNT_DUMP     2
+#define        RPCMNT_UMOUNT   3
+#define        RPCMNT_UMNTALL  4
+#define        RPCMNT_EXPORT   5
+#define        RPCMNT_NAMELEN  255
+#define        RPCMNT_PATHLEN  1024
+#define        RPCPROG_NFS     100003
diff --git a/sys/lib/libsa/saerrno.h b/sys/lib/libsa/saerrno.h
new file mode 100644 (file)
index 0000000..f0a70fb
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: saerrno.h,v 1.11 2007/12/03 09:51:31 isaki Exp $       */
+
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)saerrno.h   8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/errno.h>
+
+extern int errno;
+
+/* special stand error codes */
+#define        EADAPT  (ELAST+1)       /* bad adaptor */
+#define        ECTLR   (ELAST+2)       /* bad controller */
+#define        EUNIT   (ELAST+3)       /* bad drive */
+#define        EPART   (ELAST+4)       /* bad partition */
+#define        ERDLAB  (ELAST+5)       /* can't read disk label */
+#define        EUNLAB  (ELAST+6)       /* unlabeled disk */
+#define        EOFFSET (ELAST+7)       /* relative seek not supported */
+#define        ECMD    (ELAST+8)       /* undefined driver command */
+#define        EBSE    (ELAST+9)       /* bad sector error */
+#define        EWCK    (ELAST+10)      /* write check error */
+#define        EECC    (ELAST+11)      /* uncorrectable ecc error */
+#define        EHER    (ELAST+12)      /* hard error */
+#define        ESALAST (ELAST+12)      /* */
diff --git a/sys/lib/libsa/saioctl.h b/sys/lib/libsa/saioctl.h
new file mode 100644 (file)
index 0000000..8b0198a
--- /dev/null
@@ -0,0 +1,48 @@
+/*     $NetBSD: saioctl.h,v 1.4 2005/12/11 12:24:46 christos Exp $     */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)saioctl.h   8.1 (Berkeley) 6/11/93
+ */
+
+/* ioctl's -- for disks just now */
+#define        SAIOHDR         (('d'<<8)|1)    /* next i/o includes header */
+#define        SAIOCHECK       (('d'<<8)|2)    /* next i/o checks data */
+#define        SAIOHCHECK      (('d'<<8)|3)    /* next i/o checks header & data */
+#define        SAIONOBAD       (('d'<<8)|4)    /* inhibit bad sector forwarding */
+#define        SAIODOBAD       (('d'<<8)|5)    /* enable bad sector forwarding */
+#define        SAIOECCLIM      (('d'<<8)|6)    /* set limit to ecc correction, bits */
+#define        SAIOECCUNL      (('d'<<8)|7)    /* use standard ecc procedures */
+#define        SAIORETRIES     (('d'<<8)|8)    /* set retry count for unit */
+#define        SAIODEVDATA     (('d'<<8)|9)    /* get pointer to pack label */
+#define        SAIOSSI         (('d'<<8)|10)   /* set skip sector inhibit */
+#define        SAIONOSSI       (('d'<<8)|11)   /* inhibit skip sector handling */
+#define        SAIOSSDEV       (('d'<<8)|12)   /* is device skip sector type? */
+#define        SAIODEBUG       (('d'<<8)|13)   /* enable/disable debugging */
+#define        SAIOGBADINFO    (('d'<<8)|14)   /* get bad-sector table */
diff --git a/sys/lib/libsa/snprintf.c b/sys/lib/libsa/snprintf.c
new file mode 100644 (file)
index 0000000..f5ccf97
--- /dev/null
@@ -0,0 +1,50 @@
+/*     $NetBSD: snprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stdarg.h>
+
+#include "stand.h"
+
+int
+snprintf(char *buf, size_t size, const char *fmt, ...)
+{
+       va_list ap;
+       int len;
+
+       va_start(ap, fmt);
+       len = vsnprintf(buf, size, fmt, ap);
+       va_end(ap);
+       return len;
+}
diff --git a/sys/lib/libsa/sprintf.c b/sys/lib/libsa/sprintf.c
new file mode 100644 (file)
index 0000000..a34e59e
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: sprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $        */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "stand.h"
+
+int
+sprintf(char *buf, const char *fmt, ...)
+{
+       va_list ap;
+       int len;
+
+       va_start(ap, fmt);
+       len = vsnprintf(buf, -(size_t)buf, fmt, ap);
+       va_end(ap);
+       return len;
+}
diff --git a/sys/lib/libsa/stand.h b/sys/lib/libsa/stand.h
new file mode 100644 (file)
index 0000000..a9d5720
--- /dev/null
@@ -0,0 +1,327 @@
+/*     $NetBSD: stand.h,v 1.74 2011/12/25 06:09:08 tsutsui Exp $       */
+
+/*
+ * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)stand.h     8.1 (Berkeley) 6/11/93
+ */
+
+#ifndef _LIBSA_STAND_H_
+#define        _LIBSA_STAND_H_
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/stat.h>
+#include <sys/stdarg.h>
+#include "saioctl.h"
+#include "saerrno.h"
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#ifdef LIBSA_RENAME_PRINTF
+#define getchar                libsa_getchar
+#define gets           libsa_gets
+#define printf         libsa_printf
+#define putchar                libsa_putchar
+#define sprintf                libsa_sprintf
+#define vprintf                libsa_vprintf
+#define vsprintf       libsa_vsprintf
+#endif
+
+struct open_file;
+
+#define FS_DEF_BASE(fs) \
+       extern __compactcall int        __CONCAT(fs,_open)(const char *, struct open_file *); \
+       extern __compactcall int        __CONCAT(fs,_close)(struct open_file *); \
+       extern __compactcall int        __CONCAT(fs,_read)(struct open_file *, void *, \
+                                               size_t, size_t *); \
+       extern __compactcall int        __CONCAT(fs,_write)(struct open_file *, void *, \
+                                               size_t, size_t *); \
+       extern __compactcall off_t      __CONCAT(fs,_seek)(struct open_file *, off_t, int); \
+       extern __compactcall int        __CONCAT(fs,_stat)(struct open_file *, struct stat *)
+
+#if defined(LIBSA_ENABLE_LS_OP)
+#define FS_DEF(fs) \
+       FS_DEF_BASE(fs);\
+       extern __compactcall void       __CONCAT(fs,_ls)(struct open_file *, const char *)
+#else
+#define FS_DEF(fs) FS_DEF_BASE(fs)
+#endif
+
+
+/*
+ * This structure is used to define file system operations in a file system
+ * independent way.
+ */
+extern char *fsmod;
+extern char *fsmod2;
+
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+struct fs_ops {
+       __compactcall int       (*open)(const char *, struct open_file *);
+       __compactcall int       (*close)(struct open_file *);
+       __compactcall int       (*read)(struct open_file *, void *, size_t, size_t *);
+       __compactcall int       (*write)(struct open_file *, void *, size_t size, size_t *);
+       __compactcall off_t     (*seek)(struct open_file *, off_t, int);
+       __compactcall int       (*stat)(struct open_file *, struct stat *);
+#if defined(LIBSA_ENABLE_LS_OP)
+       __compactcall void      (*ls)(struct open_file *, const char *);
+#endif
+};
+
+extern struct fs_ops file_system[];
+extern int nfsys;
+
+#if defined(LIBSA_ENABLE_LS_OP)
+#define FS_OPS(fs) { \
+       __CONCAT(fs,_open), \
+       __CONCAT(fs,_close), \
+       __CONCAT(fs,_read), \
+       __CONCAT(fs,_write), \
+       __CONCAT(fs,_seek), \
+       __CONCAT(fs,_stat), \
+       __CONCAT(fs,_ls) }
+#else
+#define FS_OPS(fs) { \
+       __CONCAT(fs,_open), \
+       __CONCAT(fs,_close), \
+       __CONCAT(fs,_read), \
+       __CONCAT(fs,_write), \
+       __CONCAT(fs,_seek), \
+       __CONCAT(fs,_stat) }
+#endif
+
+#define        FS_OPEN(fs)             ((fs)->open)
+#define        FS_CLOSE(fs)            ((fs)->close)
+#define        FS_READ(fs)             ((fs)->read)
+#define        FS_WRITE(fs)            ((fs)->write)
+#define        FS_SEEK(fs)             ((fs)->seek)
+#define        FS_STAT(fs)             ((fs)->stat)
+#if defined(LIBSA_ENABLE_LS_OP)
+#define        FS_LS(fs)               ((fs)->ls)
+#endif
+
+#else
+
+#define        FS_OPEN(fs)             ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_open)
+#define        FS_CLOSE(fs)            ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_close)
+#define        FS_READ(fs)             ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_read)
+#define        FS_WRITE(fs)            ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_write)
+#define        FS_SEEK(fs)             ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_seek)
+#define        FS_STAT(fs)             ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_stat)
+#if defined(LIBSA_ENABLE_LS_OP)
+#define        FS_LS(fs)               ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_ls)
+#endif
+
+FS_DEF(LIBSA_SINGLE_FILESYSTEM);
+
+#endif
+
+/* where values for lseek(2) */
+#define        SEEK_SET        0       /* set file offset to offset */
+#define        SEEK_CUR        1       /* set file offset to current plus offset */
+#define        SEEK_END        2       /* set file offset to EOF plus offset */
+
+/* Device switch */
+#if !defined(LIBSA_SINGLE_DEVICE)
+
+struct devsw {
+       char    *dv_name;
+       int     (*dv_strategy)(void *, int, daddr_t, size_t, void *, size_t *);
+       int     (*dv_open)(struct open_file *, ...);
+       int     (*dv_close)(struct open_file *);
+       int     (*dv_ioctl)(struct open_file *, u_long, void *);
+};
+
+extern struct devsw devsw[];   /* device array */
+extern int ndevs;              /* number of elements in devsw[] */
+
+#define        DEV_NAME(d)             ((d)->dv_name)
+#define        DEV_STRATEGY(d)         ((d)->dv_strategy)
+#define        DEV_OPEN(d)             ((d)->dv_open)
+#define        DEV_CLOSE(d)            ((d)->dv_close)
+#define        DEV_IOCTL(d)            ((d)->dv_ioctl)
+
+#else
+
+#define        DEV_NAME(d)             ___STRING(LIBSA_SINGLE_DEVICE)
+#define        DEV_STRATEGY(d)         ___CONCAT(LIBSA_SINGLE_DEVICE,strategy)
+#define        DEV_OPEN(d)             ___CONCAT(LIBSA_SINGLE_DEVICE,open)
+#define        DEV_CLOSE(d)            ___CONCAT(LIBSA_SINGLE_DEVICE,close)
+#define        DEV_IOCTL(d)            ___CONCAT(LIBSA_SINGLE_DEVICE,ioctl)
+
+/* These may be #defines which must not be expanded here, hence the extra () */
+int    (DEV_STRATEGY(unused))(void *, int, daddr_t, size_t, void *, size_t *);
+int    (DEV_OPEN(unused))(struct open_file *, ...);
+int    (DEV_CLOSE(unused))(struct open_file *);
+int    (DEV_IOCTL(unused))(struct open_file *, u_long, void *);
+
+#endif
+
+struct open_file {
+       int             f_flags;        /* see F_* below */
+#if !defined(LIBSA_SINGLE_DEVICE)
+       const struct devsw      *f_dev; /* pointer to device operations */
+#endif
+       void            *f_devdata;     /* device specific data */
+#if !defined(LIBSA_SINGLE_FILESYSTEM)
+       const struct fs_ops     *f_ops; /* pointer to file system operations */
+#endif
+       void            *f_fsdata;      /* file system specific data */
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       off_t           f_offset;       /* current file offset (F_RAW) */
+#endif
+};
+
+#define        SOPEN_MAX       4
+extern struct open_file files[];
+
+/* f_flags values */
+#define        F_READ          0x0001  /* file opened for reading */
+#define        F_WRITE         0x0002  /* file opened for writing */
+#if !defined(LIBSA_NO_RAW_ACCESS)
+#define        F_RAW           0x0004  /* raw device open - no file system */
+#endif
+#define F_NODEV                0x0008  /* network open - no device */
+
+int    (devopen)(struct open_file *, const char *, char **);
+#ifdef HEAP_VARIABLE
+void   setheap(void *, void *);
+#endif
+void   *alloc(size_t) __compactcall;
+void   dealloc(void *, size_t) __compactcall;
+struct disklabel;
+char   *getdisklabel(const char *, struct disklabel *);
+int    dkcksum(const struct disklabel *);
+
+void   printf(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+int    sprintf(char *, const char *, ...)
+    __attribute__((__format__(__printf__, 2, 3)));
+int    snprintf(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__, 3, 4)));
+void   vprintf(const char *, va_list)
+    __attribute__((__format__(__printf__, 1, 0)));
+int    vsprintf(char *, const char *, va_list)
+    __attribute__((__format__(__printf__, 2, 0)));
+int    vsnprintf(char *, size_t, const char *, va_list)
+    __attribute__((__format__(__printf__, 3, 0)));
+void   twiddle(void);
+void   gets(char *);
+int    getfile(char *prompt, int mode);
+char   *strerror(int);
+__dead void    exit(int);
+__dead void    panic(const char *, ...)
+    __attribute__((__format__(__printf__, 1, 2)));
+__dead void    _rtt(void);
+void   *memcpy(void *, const void *, size_t);
+void   *memmove(void *, const void *, size_t);
+int    memcmp(const void *, const void *, size_t);
+void   *memset(void *, int, size_t);
+void   exec(char *, char *, int);
+int    open(const char *, int);
+int    close(int);
+void   closeall(void);
+ssize_t        read(int, void *, size_t);
+ssize_t        write(int, const void *, size_t);
+off_t  lseek(int, off_t, int);
+int    ioctl(int, u_long, char *);
+int    stat(const char *, struct stat *);
+int    fstat(int, struct stat *);
+#if defined(LIBSA_ENABLE_LS_OP)
+void   ls(const char *);
+#endif
+
+typedef int cmp_t(const void *, const void *);
+void   qsort(void *, size_t, size_t, cmp_t *);
+
+extern int opterr, optind, optopt, optreset;
+extern char *optarg;
+int    getopt(int, char * const *, const char *);
+
+char   *getpass(const char *);
+int    checkpasswd(void);
+int    check_password(const char *);
+
+int    nodev(void);
+int    noioctl(struct open_file *, u_long, void *);
+void   nullsys(void);
+
+FS_DEF(null);
+
+/* Machine dependent functions */
+void   machdep_start(char *, int, char *, char *, char *);
+int    getchar(void);
+void   putchar(int);
+
+#ifdef __INTERNAL_LIBSA_CREAD
+int    oopen(const char *, int);
+int    oclose(int);
+ssize_t        oread(int, void *, size_t);
+off_t  olseek(int, off_t, int);
+#endif
+
+extern const char hexdigits[];
+
+/* XXX: These should be removed eventually. */
+void   bcopy(const void *, void *, size_t);
+void   bzero(void *, size_t);
+
+#endif /* _LIBSA_STAND_H_ */
diff --git a/sys/lib/libsa/stat.c b/sys/lib/libsa/stat.c
new file mode 100644 (file)
index 0000000..3387e80
--- /dev/null
@@ -0,0 +1,47 @@
+/*     $NetBSD: stat.c,v 1.7 2007/11/24 13:20:57 isaki Exp $   */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)stat.c      8.1 (Berkeley) 6/11/93
+ */
+
+#include "stand.h"
+
+int
+stat(const char *str, struct stat *sb)
+{
+       int fd, rv;
+
+       fd = open(str, 0);
+       if (fd < 0)
+               return -1;
+       rv = fstat(fd, sb);
+       (void)close(fd);
+       return rv;
+}
diff --git a/sys/lib/libsa/strerror.c b/sys/lib/libsa/strerror.c
new file mode 100644 (file)
index 0000000..3e03aba
--- /dev/null
@@ -0,0 +1,72 @@
+/*     $NetBSD: strerror.c,v 1.20 2007/11/24 13:20:57 isaki Exp $      */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include "saerrno.h"
+#include "stand.h"
+
+static const struct mi {
+       int     errno;
+       const char *msg;
+} errlist[] = {
+       { EADAPT,       "bad adaptor number" },
+       { ECTLR,        "bad controller number" },
+       { EUNIT,        "bad drive number" },
+       { EPART,        "bad partition" },
+       { ERDLAB,       "can't read disk label" },
+       { EUNLAB,       "unlabeled" },
+       { ENXIO,        "Device not configured" },
+       { EPERM,        "Operation not permitted" },
+       { ENOENT,       "No such file or directory" },
+       { ESTALE,       "Stale NFS file handle" },
+       { EFTYPE,       "Inappropriate file type or format" },
+       { ENOEXEC,      "Exec format error" },
+       { EIO,          "Input/output error" },
+       { EINVAL,       "Invalid argument" },
+       { ENOTDIR,      "Not a directory" },
+       { EOFFSET,      "invalid file offset" },
+       { EACCES,       "Permission denied" },
+       { 0, 0 },
+};
+
+char *
+strerror(int err)
+{
+       static  char ebuf[36];
+       const struct mi *mi;
+
+       for (mi = errlist; mi->msg; mi++)
+               if (mi->errno == err)
+                       return __UNCONST(mi->msg);
+
+       snprintf(ebuf, sizeof ebuf, "Unknown error: code %d", err);
+       return ebuf;
+}
diff --git a/sys/lib/libsa/subr_prf.c b/sys/lib/libsa/subr_prf.c
new file mode 100644 (file)
index 0000000..e464890
--- /dev/null
@@ -0,0 +1,332 @@
+/*     $NetBSD: subr_prf.c,v 1.21 2011/07/17 20:54:52 joerg Exp $      */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Scaled down version of printf(3).
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stdint.h>                /* XXX: for intptr_t */
+
+#include "stand.h"
+
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define INTMAX_T       longlong_t
+#define UINTMAX_T      u_longlong_t
+#else
+#define INTMAX_T       long
+#define UINTMAX_T      u_long
+#endif
+
+#if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
+#define PTRDIFF_T      ptrdiff_t
+#else
+#define PTRDIFF_T      intptr_t
+#endif
+
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
+#else
+static void kprintn(void (*)(int), UINTMAX_T, int);
+#endif
+static void sputchar(int);
+static void kdoprnt(void (*)(int), const char *, va_list);
+
+static char *sbuf, *ebuf;
+
+const char hexdigits[16] = "0123456789abcdef";
+
+#define LONG           0x01
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define LLONG          0x02
+#endif
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+#define ALT            0x04
+#define SPACE          0x08
+#define LADJUST                0x10
+#define SIGN           0x20
+#define ZEROPAD                0x40
+#define NEGATIVE       0x80
+#define KPRINTN(base)  kprintn(put, ul, base, lflag, width)
+#define RZERO()                                                        \
+do {                                                           \
+       if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) {           \
+               while (width-- > 0)                             \
+                       put('0');                               \
+       }                                                       \
+} while (/*CONSTCOND*/0)
+#define RPAD()                                                 \
+do {                                                           \
+       if (lflag & LADJUST) {                                  \
+               while (width-- > 0)                             \
+                       put(' ');                               \
+       }                                                       \
+} while (/*CONSTCOND*/0)
+#define LPAD()                                                 \
+do {                                                           \
+       if ((lflag & (ZEROPAD|LADJUST)) == 0) {                 \
+               while (width-- > 0)                             \
+                       put(' ');                               \
+       }                                                       \
+} while (/*CONSTCOND*/0)
+#else  /* LIBSA_PRINTF_WIDTH_SUPPORT */
+#define KPRINTN(base)  kprintn(put, ul, base)
+#define RZERO()                /**/
+#define RPAD()         /**/
+#define LPAD()         /**/
+#endif /* LIBSA_PRINTF_WIDTH_SUPPORT */
+
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+#define KPRINT(base)                                           \
+do {                                                           \
+       ul = (lflag & LLONG)                                    \
+           ? va_arg(ap, u_longlong_t)                          \
+           : (lflag & LONG)                                    \
+               ? va_arg(ap, u_long)                            \
+               : va_arg(ap, u_int);                            \
+       KPRINTN(base);                                          \
+} while (/*CONSTCOND*/0)
+#else  /* LIBSA_PRINTF_LONGLONG_SUPPORT */
+#define KPRINT(base)                                           \
+do {                                                           \
+       ul = (lflag & LONG)                                     \
+           ? va_arg(ap, u_long) : va_arg(ap, u_int);           \
+       KPRINTN(base);                                          \
+} while (/*CONSTCOND*/0)
+#endif /* LIBSA_PRINTF_LONGLONG_SUPPORT */
+
+static void
+sputchar(int c)
+{
+
+       if (sbuf < ebuf)
+               *sbuf++ = c;
+}
+
+void
+vprintf(const char *fmt, va_list ap)
+{
+
+       kdoprnt(putchar, fmt, ap);
+}
+
+int
+vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
+{
+
+       sbuf = buf;
+       ebuf = buf + size - 1;
+       kdoprnt(sputchar, fmt, ap);
+       *sbuf = '\0';
+       return sbuf - buf;
+}
+
+static void
+kdoprnt(void (*put)(int), const char *fmt, va_list ap)
+{
+       char *p;
+       int ch;
+       UINTMAX_T ul;
+       int lflag;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+       int width;
+       char *q;
+#endif
+
+       for (;;) {
+               while ((ch = *fmt++) != '%') {
+                       if (ch == '\0')
+                               return;
+                       put(ch);
+               }
+               lflag = 0;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+               width = 0;
+#endif
+reswitch:
+               switch (ch = *fmt++) {
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+               case '#':
+                       lflag |= ALT;
+                       goto reswitch;
+               case ' ':
+                       lflag |= SPACE;
+                       goto reswitch;
+               case '-':
+                       lflag |= LADJUST;
+                       goto reswitch;
+               case '+':
+                       lflag |= SIGN;
+                       goto reswitch;
+               case '0':
+                       lflag |= ZEROPAD;
+                       goto reswitch;
+               case '1': case '2': case '3': case '4': case '5':
+               case '6': case '7': case '8': case '9':
+                       for (;;) {
+                               width *= 10;
+                               width += ch - '0';
+                               ch = *fmt;
+                               if ((unsigned)ch - '0' > 9)
+                                       break;
+                               ++fmt;
+                       }
+#endif
+                       goto reswitch;
+               case 'l':
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+                       if (*fmt == 'l') {
+                               ++fmt;
+                               lflag |= LLONG;
+                       } else
+#endif
+                               lflag |= LONG;
+                       goto reswitch;
+               case 't':
+                       if (sizeof(PTRDIFF_T) == sizeof(long))
+                               lflag |= LONG;
+                       goto reswitch;
+               case 'z':
+                       if (sizeof(ssize_t) == sizeof(long))
+                               lflag |= LONG;
+                       goto reswitch;
+               case 'c':
+                       ch = va_arg(ap, int);
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+                       --width;
+#endif
+                       RPAD();
+                       put(ch & 0xFF);
+                       LPAD();
+                       break;
+               case 's':
+                       p = va_arg(ap, char *);
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+                       for (q = p; *q != '\0'; ++q)
+                               continue;
+                       width -= q - p;
+#endif
+                       RPAD();
+                       while ((ch = (unsigned char)*p++))
+                               put(ch);
+                       LPAD();
+                       break;
+               case 'd':
+                       ul =
+#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
+                       (lflag & LLONG) ? va_arg(ap, longlong_t) :
+#endif
+                       (lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
+                       if ((INTMAX_T)ul < 0) {
+                               ul = -(INTMAX_T)ul;
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+                               lflag |= NEGATIVE;
+#else
+                               put('-');
+#endif
+                       }
+                       KPRINTN(10);
+                       break;
+               case 'o':
+                       KPRINT(8);
+                       break;
+               case 'u':
+                       KPRINT(10);
+                       break;
+               case 'p':
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+                       lflag |= (LONG|ALT);
+#else
+                       put('0');
+                       put('x');
+#endif
+                       /* FALLTHROUGH */
+               case 'x':
+                       KPRINT(16);
+                       break;
+               default:
+                       if (ch == '\0')
+                               return;
+                       put(ch);
+                       break;
+               }
+       }
+}
+
+static void
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
+#else
+kprintn(void (*put)(int), UINTMAX_T ul, int base)
+#endif
+{
+                                       /* hold a INTMAX_T in base 8 */
+       char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+       char *q;
+#endif
+
+       p = buf;
+       do {
+               *p++ = hexdigits[ul % base];
+       } while (ul /= base);
+#ifdef LIBSA_PRINTF_WIDTH_SUPPORT
+       q = p;
+       if (lflag & ALT && *(p - 1) != '0') {
+               if (base == 8) {
+                       *p++ = '0';
+               } else if (base == 16) {
+                       *p++ = 'x';
+                       *p++ = '0';
+               }
+       }
+       if (lflag & NEGATIVE)
+               *p++ = '-';
+       else if (lflag & SIGN)
+               *p++ = '+';
+       else if (lflag & SPACE)
+               *p++ = ' ';
+       width -= p - buf;
+       if ((lflag & LADJUST) == 0) {
+               while (p > q)
+                       put(*--p);
+       }
+#endif
+       RPAD();
+       RZERO();
+       do {
+               put(*--p);
+       } while (p > buf);
+       LPAD();
+}
diff --git a/sys/lib/libsa/tftp.c b/sys/lib/libsa/tftp.c
new file mode 100644 (file)
index 0000000..f6a025d
--- /dev/null
@@ -0,0 +1,459 @@
+/*     $NetBSD: tftp.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $         */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Simple TFTP implementation for libsa.
+ * Assumes:
+ *  - socket descriptor (int) at open_file->f_devdata
+ *  - server host IP in global servip
+ * Restrictions:
+ *  - read only
+ *  - lseek only with SEEK_SET or SEEK_CUR
+ *  - no big time differences between transfers (<tftp timeout)
+ */
+
+/*
+ * XXX Does not currently implement:
+ * XXX
+ * XXX LIBSA_NO_FS_CLOSE
+ * XXX LIBSA_NO_FS_SEEK
+ * XXX LIBSA_NO_FS_WRITE
+ * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?)
+ * XXX LIBSA_FS_SINGLECOMPONENT (does this even make sense?)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <netinet/in_systm.h>
+#include <lib/libkern/libkern.h>
+
+#include "stand.h"
+#include "net.h"
+
+#include "tftp.h"
+
+extern struct in_addr servip;
+
+static int      tftpport = 2000;
+
+#define RSPACE 520             /* max data packet, rounded up */
+
+struct tftp_handle {
+       struct iodesc  *iodesc;
+       int             currblock;      /* contents of lastdata */
+       int             islastblock;    /* flag */
+       int             validsize;
+       int             off;
+       const char     *path;   /* saved for re-requests */
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct tftphdr t;
+               u_char space[RSPACE];
+       } lastdata;
+};
+
+static const int tftperrors[8] = {
+       0,                      /* ??? */
+       ENOENT,
+       EPERM,
+       ENOSPC,
+       EINVAL,                 /* ??? */
+       EINVAL,                 /* ??? */
+       EEXIST,
+       EINVAL,                 /* ??? */
+};
+
+static ssize_t recvtftp(struct iodesc *, void *, size_t, saseconds_t);
+static int tftp_makereq(struct tftp_handle *);
+static int tftp_getnextblock(struct tftp_handle *);
+#ifndef TFTP_NOTERMINATE
+static void tftp_terminate(struct tftp_handle *);
+#endif
+static ssize_t tftp_size_of_file(struct tftp_handle *tftpfile);
+
+static ssize_t
+recvtftp(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       ssize_t n;
+       struct tftphdr *t;
+
+       errno = 0;
+
+       n = readudp(d, pkt, len, tleft);
+
+       if (n < 4)
+               return -1;
+
+       t = (struct tftphdr *)pkt;
+       switch (ntohs(t->th_opcode)) {
+       case DATA:
+               if (htons(t->th_block) != d->xid) {
+                       /*
+                        * Expected block?
+                        */
+                       return -1;
+               }
+               if (d->xid == 1) {
+                       /*
+                        * First data packet from new port.
+                        */
+                       struct udphdr *uh;
+                       uh = (struct udphdr *)pkt - 1;
+                       d->destport = uh->uh_sport;
+               } /* else check uh_sport has not changed??? */
+               return (n - (t->th_data - (char *)t));
+       case ERROR:
+               if ((unsigned int)ntohs(t->th_code) >= 8) {
+                       printf("illegal tftp error %d\n", ntohs(t->th_code));
+                       errno = EIO;
+               } else {
+#ifdef DEBUG
+                       printf("tftp-error %d\n", ntohs(t->th_code));
+#endif
+                       errno = tftperrors[ntohs(t->th_code)];
+               }
+               return -1;
+       default:
+#ifdef DEBUG
+               printf("tftp type %d not handled\n", ntohs(t->th_opcode));
+#endif
+               return -1;
+       }
+}
+
+/* send request, expect first block (or error) */
+static int
+tftp_makereq(struct tftp_handle *h)
+{
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct tftphdr t;
+               u_char space[FNAME_SIZE + 6];
+       } wbuf;
+       char           *wtail;
+       int             l;
+       ssize_t         res;
+       struct tftphdr *t;
+
+       wbuf.t.th_opcode = htons((u_short)RRQ);
+       wtail = wbuf.t.th_stuff;
+       l = strlen(h->path);
+       (void)memcpy(wtail, h->path, l + 1);
+       wtail += l + 1;
+       (void)memcpy(wtail, "octet", 6);
+       wtail += 6;
+
+       t = &h->lastdata.t;
+
+       /* h->iodesc->myport = htons(--tftpport); */
+       h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
+       h->iodesc->destport = htons(IPPORT_TFTP);
+       h->iodesc->xid = 1;     /* expected block */
+
+       res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *)&wbuf.t,
+                      recvtftp, t, sizeof(*t) + RSPACE);
+
+       if (res == -1)
+               return errno;
+
+       h->currblock = 1;
+       h->validsize = res;
+       h->islastblock = 0;
+       if (res < SEGSIZE)
+               h->islastblock = 1;     /* very short file */
+       return 0;
+}
+
+/* ack block, expect next */
+static int
+tftp_getnextblock(struct tftp_handle *h)
+{
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct tftphdr t;
+       } wbuf;
+       char           *wtail;
+       int             res;
+       struct tftphdr *t;
+
+       wbuf.t.th_opcode = htons((u_short)ACK);
+       wbuf.t.th_block = htons((u_short)h->currblock);
+       wtail = (char *)&wbuf.t.th_data;
+
+       t = &h->lastdata.t;
+
+       h->iodesc->xid = h->currblock + 1;      /* expected block */
+
+       res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *)&wbuf.t,
+                      recvtftp, t, sizeof(*t) + RSPACE);
+
+       if (res == -1)          /* 0 is OK! */
+               return errno;
+
+       h->currblock++;
+       h->validsize = res;
+       if (res < SEGSIZE)
+               h->islastblock = 1;     /* EOF */
+       return 0;
+}
+
+#ifndef TFTP_NOTERMINATE
+static void
+tftp_terminate(struct tftp_handle *h)
+{
+       struct {
+               u_char header[UDP_TOTAL_HEADER_SIZE];
+               struct tftphdr t;
+       } wbuf;
+       char           *wtail;
+
+       wtail = (char *)&wbuf.t.th_data;
+       if (h->islastblock) {
+               wbuf.t.th_opcode = htons((u_short)ACK);
+               wbuf.t.th_block = htons((u_short)h->currblock);
+       } else {
+               wbuf.t.th_opcode = htons((u_short)ERROR);
+               wbuf.t.th_code = htons((u_short)ENOSPACE); /* ??? */
+               *wtail++ = '\0'; /* empty error string */
+       }
+
+       (void)sendudp(h->iodesc, &wbuf.t, wtail - (char *)&wbuf.t);
+}
+#endif
+
+__compactcall int
+tftp_open(const char *path, struct open_file *f)
+{
+       struct tftp_handle *tftpfile;
+       struct iodesc  *io;
+       int             res;
+
+       tftpfile = (struct tftp_handle *)alloc(sizeof(*tftpfile));
+       if (!tftpfile)
+               return ENOMEM;
+
+       tftpfile->iodesc = io = socktodesc(*(int *)(f->f_devdata));
+       io->destip = servip;
+       tftpfile->off = 0;
+       tftpfile->path = path;  /* XXXXXXX we hope it's static */
+
+       res = tftp_makereq(tftpfile);
+
+       if (res) {
+               dealloc(tftpfile, sizeof(*tftpfile));
+               return res;
+       }
+       f->f_fsdata = (void *)tftpfile;
+       fsmod = "nfs";
+       return 0;
+}
+
+__compactcall int
+tftp_read(struct open_file *f, void *addr, size_t size, size_t *resid)
+{
+       struct tftp_handle *tftpfile;
+#if !defined(LIBSA_NO_TWIDDLE)
+       static int      tc = 0;
+#endif
+       tftpfile = (struct tftp_handle *)f->f_fsdata;
+
+       while (size > 0) {
+               int needblock;
+               size_t count;
+
+#if !defined(LIBSA_NO_TWIDDLE)
+               if (!(tc++ % 16))
+                       twiddle();
+#endif
+
+               needblock = tftpfile->off / SEGSIZE + 1;
+
+               if (tftpfile->currblock > needblock) {  /* seek backwards */
+#ifndef TFTP_NOTERMINATE
+                       tftp_terminate(tftpfile);
+#endif
+                       tftp_makereq(tftpfile); /* no error check, it worked
+                                                * for open */
+               }
+
+               while (tftpfile->currblock < needblock) {
+                       int res;
+
+                       res = tftp_getnextblock(tftpfile);
+                       if (res) {      /* no answer */
+#ifdef DEBUG
+                               printf("tftp: read error (block %d->%d)\n",
+                                      tftpfile->currblock, needblock);
+#endif
+                               return res;
+                       }
+                       if (tftpfile->islastblock)
+                               break;
+               }
+
+               if (tftpfile->currblock == needblock) {
+                       size_t offinblock, inbuffer;
+
+                       offinblock = tftpfile->off % SEGSIZE;
+
+                       if (offinblock > tftpfile->validsize) {
+#ifdef DEBUG
+                               printf("tftp: invalid offset %d\n",
+                                   tftpfile->off);
+#endif
+                               return EINVAL;
+                       }
+                       inbuffer = tftpfile->validsize - offinblock;
+                       count = (size < inbuffer ? size : inbuffer);
+                       (void)memcpy(addr,
+                           tftpfile->lastdata.t.th_data + offinblock,
+                           count);
+
+                       addr = (char *)addr + count;
+                       tftpfile->off += count;
+                       size -= count;
+
+                       if ((tftpfile->islastblock) && (count == inbuffer))
+                               break;  /* EOF */
+               } else {
+#ifdef DEBUG
+                       printf("tftp: block %d not found\n", needblock);
+#endif
+                       return EINVAL;
+               }
+
+       }
+
+       if (resid)
+               *resid = size;
+       return 0;
+}
+
+__compactcall int
+tftp_close(struct open_file *f)
+{
+       struct tftp_handle *tftpfile;
+       tftpfile = (struct tftp_handle *)f->f_fsdata;
+
+#ifdef TFTP_NOTERMINATE
+       /* let it time out ... */
+#else
+       tftp_terminate(tftpfile);
+#endif
+
+       dealloc(tftpfile, sizeof(*tftpfile));
+       return 0;
+}
+
+__compactcall int
+tftp_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+
+static ssize_t 
+tftp_size_of_file(struct tftp_handle *tftpfile)
+{
+       ssize_t filesize;
+
+       if (tftpfile->currblock > 1) {  /* move to start of file */
+#ifndef TFTP_NOTERMINATE
+               tftp_terminate(tftpfile);
+#endif
+               tftp_makereq(tftpfile); /* no error check, it worked
+                                        * for open */
+       }
+
+       /* start with the size of block 1 */
+       filesize = tftpfile->validsize;
+
+       /* and keep adding the sizes till we hit the last block */
+       while (!tftpfile->islastblock) {
+               int res;
+
+               res = tftp_getnextblock(tftpfile);
+               if (res) {      /* no answer */
+#ifdef DEBUG
+                       printf("tftp: read error (block %d)\n",
+                                       tftpfile->currblock);
+#endif
+                       return -1;
+               }
+               filesize += tftpfile->validsize;
+       }
+#ifdef DEBUG
+       printf("tftp_size_of_file: file is %zu bytes\n", filesize);
+#endif
+       return filesize;
+}
+
+__compactcall int
+tftp_stat(struct open_file *f, struct stat *sb)
+{
+       struct tftp_handle *tftpfile;
+       tftpfile = (struct tftp_handle *)f->f_fsdata;
+
+       sb->st_mode = 0444;
+       sb->st_nlink = 1;
+       sb->st_uid = 0;
+       sb->st_gid = 0;
+       sb->st_size = tftp_size_of_file(tftpfile);
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+tftp_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by tftp\n");
+       return;
+}
+#endif
+
+__compactcall off_t
+tftp_seek(struct open_file *f, off_t offset, int where)
+{
+       struct tftp_handle *tftpfile;
+       tftpfile = (struct tftp_handle *)f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               tftpfile->off = offset;
+               break;
+       case SEEK_CUR:
+               tftpfile->off += offset;
+               break;
+       default:
+               errno = EOFFSET;
+               return -1;
+       }
+       return tftpfile->off;
+}
diff --git a/sys/lib/libsa/tftp.h b/sys/lib/libsa/tftp.h
new file mode 100644 (file)
index 0000000..4be48f9
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: tftp.h,v 1.6 2005/12/11 12:24:46 christos Exp $        */
+
+/*
+ * Copyright (c) 1996
+ *     Matthias Drochner.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*     NetBSD: tftp.h,v 1.6 2000/10/18 01:35:46 dogcow Exp     */
+
+/*
+ * Copyright (c) 1983, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)tftp.h      8.1 (Berkeley) 6/2/93
+ */
+/*
+ * Trivial File Transfer Protocol (IEN-133)
+ */
+#define        SEGSIZE         512             /* data segment size */
+
+/*
+ * Packet types.
+ */
+#define        RRQ     01                      /* read request */
+#define        WRQ     02                      /* write request */
+#define        DATA    03                      /* data packet */
+#define        ACK     04                      /* acknowledgement */
+#define        ERROR   05                      /* error code */
+
+struct tftphdr {
+       short   th_opcode;              /* packet type */
+       union {
+               unsigned short tu_block; /* block # */
+               short   tu_code;        /* error code */
+               char    tu_stuff[1];    /* request packet stuff */
+       } th_u;
+       char    th_data[1];             /* data or error string */
+};
+
+#define        th_block        th_u.tu_block
+#define        th_code         th_u.tu_code
+#define        th_stuff        th_u.tu_stuff
+#define        th_msg          th_data
+
+/*
+ * Error codes.
+ */
+#define        EUNDEF          0               /* not defined */
+#define        ENOTFOUND       1               /* file not found */
+#define        EACCESS         2               /* access violation */
+#define        ENOSPACE        3               /* disk full or allocation exceeded */
+#define        EBADOP          4               /* illegal TFTP operation */
+#define        EBADID          5               /* unknown transfer ID */
+#define        EEXISTS         6               /* file already exists */
+#define        ENOUSER         7               /* no such user */
+
+FS_DEF(tftp);
+
+#define IPPORT_TFTP 69
diff --git a/sys/lib/libsa/twiddle.c b/sys/lib/libsa/twiddle.c
new file mode 100644 (file)
index 0000000..7189adb
--- /dev/null
@@ -0,0 +1,52 @@
+/*     $NetBSD: twiddle.c,v 1.8 2008/04/30 16:18:09 ad Exp $   */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "stand.h"
+
+#define TWIDDLE_CHARS  "|/-\\"
+
+char   twiddle_toggle;
+
+void
+twiddle(void)
+{
+       static int pos;
+
+       if (!twiddle_toggle) {
+               putchar(TWIDDLE_CHARS[pos++ & 3]);
+               putchar('\b');
+       }
+}
diff --git a/sys/lib/libsa/udp.c b/sys/lib/libsa/udp.c
new file mode 100644 (file)
index 0000000..5966839
--- /dev/null
@@ -0,0 +1,136 @@
+/*     $NetBSD: udp.c,v 1.11 2011/05/11 16:23:40 zoltan Exp $  */
+
+/*
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include "stand.h"
+#include "net.h"
+
+
+/* Caller must leave room for ethernet, ip and udp headers in front!! */
+ssize_t
+sendudp(struct iodesc *d, void *pkt, size_t len)
+{
+       ssize_t cc;
+       struct udphdr *uh;
+
+#ifdef NET_DEBUG
+       if (debug) {
+               printf("sendudp: d=%lx called.\n", (long)d);
+               if (d) {
+                       printf("saddr: %s:%d",
+                           inet_ntoa(d->myip), ntohs(d->myport));
+                       printf(" daddr: %s:%d\n",
+                           inet_ntoa(d->destip), ntohs(d->destport));
+               }
+       }
+#endif
+
+       uh = (struct udphdr *)pkt - 1;
+       len += sizeof(*uh);
+
+       (void)memset(uh, 0, sizeof(*uh));
+
+       uh->uh_sport = d->myport;
+       uh->uh_dport = d->destport;
+       uh->uh_ulen = htons(len);
+
+       cc = sendip(d, uh, len, IPPROTO_UDP);
+       if (cc == -1)
+               return -1;
+       if ((size_t)cc != len)
+               panic("sendudp: bad write (%zd != %zu)", cc, len);
+       return (cc - sizeof(*uh));
+}
+
+/*
+ * Receive a UDP packet and validate it is for us.
+ * Caller leaves room for the headers (Ether, IP, UDP)
+ */
+ssize_t
+readudp(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft)
+{
+       ssize_t n;
+       struct udphdr *uh;
+
+       uh = (struct udphdr *)pkt - 1;
+       n = readip(d, uh, len + sizeof(*uh), tleft, IPPROTO_UDP);
+       if (n == -1 || (size_t)n < sizeof(*uh))
+               return -1;
+
+       if (uh->uh_dport != d->myport) {
+#ifdef NET_DEBUG
+               if (debug)
+                       printf("readudp: bad dport %d != %d\n",
+                               d->myport, ntohs(uh->uh_dport));
+#endif
+               return -1;
+       }
+
+       if (ntohs(uh->uh_ulen) < sizeof(*uh)) {
+#ifdef NET_DEBUG
+               if (debug)
+                       printf("readudp: bad udp len %d < %d\n",
+                               ntohs(uh->uh_ulen), (int)sizeof(*uh));
+#endif
+               return -1;
+       }
+
+       n -= sizeof(*uh);
+       return n;
+}
diff --git a/sys/lib/libsa/ufs.c b/sys/lib/libsa/ufs.c
new file mode 100644 (file)
index 0000000..63be30b
--- /dev/null
@@ -0,0 +1,1027 @@
+/*     $NetBSD: ufs.c,v 1.56 2011/12/25 06:09:08 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * Copyright (c) 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: David Golub
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ *     Stand-alone file reading package for UFS and LFS filesystems.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#ifdef LIBSA_LFS
+#include <sys/queue.h>
+#include <sys/condvar.h>
+#include <sys/mount.h>                 /* XXX for MNAMELEN */
+#include <ufs/lfs/lfs.h>
+#else
+#include <ufs/ffs/fs.h>
+#endif
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+
+#include "stand.h"
+#ifdef LIBSA_LFS
+#include "lfs.h"
+#else
+#include "ufs.h"
+#endif
+
+/* If this file is compiled by itself, build ufs (aka ffsv1) support */
+#if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS)
+#define LIBSA_FFSv1
+#endif
+
+#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
+#define LIBSA_NO_FS_SYMLINK
+#endif
+#if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS)
+#undef COMPAT_UFS
+#endif
+
+#ifdef LIBSA_LFS
+/*
+ * In-core LFS superblock.  This exists only to placate the macros in lfs.h,
+ */
+struct fs {
+       struct dlfs     lfs_dlfs;
+};
+#define fs_magic       lfs_magic
+#define fs_maxsymlinklen lfs_maxsymlinklen
+
+#define FS_MAGIC       LFS_MAGIC
+#define SBLOCKSIZE     LFS_SBPAD
+#define SBLOCKOFFSET   LFS_LABELPAD
+#else
+/* NB ufs2 doesn't use the common suberblock code... */
+#define FS_MAGIC       FS_UFS1_MAGIC
+#define SBLOCKOFFSET   SBLOCK_UFS1
+#endif
+
+#if defined(LIBSA_NO_TWIDDLE)
+#define twiddle()
+#endif
+
+#undef cgstart
+#if defined(LIBSA_FFSv2)
+#define cgstart(fc, c) cgstart_ufs2((fs), (c))
+#else
+#define cgstart(fc, c) cgstart_ufs1((fs), (c))
+#endif
+
+#ifndef ufs_dinode
+#define ufs_dinode     ufs1_dinode
+#endif
+#ifndef indp_t
+#define indp_t         int32_t
+#endif
+typedef uint32_t       ino32_t;
+#ifndef FSBTODB
+#define FSBTODB(fs, indp) fsbtodb(fs, indp)
+#endif
+
+/*
+ * To avoid having a lot of filesystem-block sized buffers lurking (which
+ * could be 32k) we only keep a few entries of the indirect block map.
+ * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
+ * ~13 times pulling in a 6M kernel.
+ * The cache size must be smaller than the smallest filesystem block,
+ * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
+ */
+#define LN2_IND_CACHE_SZ       6
+#define IND_CACHE_SZ           (1 << LN2_IND_CACHE_SZ)
+#define IND_CACHE_MASK         (IND_CACHE_SZ - 1)
+
+/*
+ * In-core open file.
+ */
+struct file {
+       off_t           f_seekp;        /* seek pointer */
+       struct fs       *f_fs;          /* pointer to super-block */
+       struct ufs_dinode       f_di;           /* copy of on-disk inode */
+       uint            f_nishift;      /* for blocks in indirect block */
+       indp_t          f_ind_cache_block;
+       indp_t          f_ind_cache[IND_CACHE_SZ];
+
+       char            *f_buf;         /* buffer for data block */
+       size_t          f_buf_size;     /* size of data block */
+       daddr_t         f_buf_blkno;    /* block number of data block */
+};
+
+static int read_inode(ino32_t, struct open_file *);
+static int block_map(struct open_file *, indp_t, indp_t *);
+static int buf_read_file(struct open_file *, char **, size_t *);
+static int search_directory(const char *, int, struct open_file *, ino32_t *);
+#ifdef LIBSA_FFSv1
+static void ffs_oldfscompat(struct fs *);
+#endif
+#ifdef LIBSA_FFSv2
+static int ffs_find_superblock(struct open_file *, struct fs *);
+#endif
+
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+       entry_t *e_next;
+       ino32_t e_ino;
+       uint8_t e_type;
+       char    e_name[1];
+};
+
+static const char    *const typestr[] = {
+       "unknown",
+       "FIFO",
+       "CHR",
+       0,
+       "DIR",
+       0,
+       "BLK",
+       0,
+       "REG",
+       0,
+       "LNK",
+       0,
+       "SOCK",
+       0,
+       "WHT"
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+       char fc, pc;
+
+       do {
+               fc = *fname++;
+               pc = *pattern++;
+               if (!fc && !pc)
+                       return 1;
+               if (pc == '?' && fc)
+                       pc = fc;
+       } while (fc == pc);
+
+       if (pc != '*')
+               return 0;
+       /*
+        * Too hard (and unnecessary really) too check for "*?name" etc....
+        * "**" will look for a '*' and "*?" a '?'
+        */
+       pc = *pattern++;
+       if (!pc)
+               return 1;
+       while ((fname = strchr(fname, pc)))
+               if (fn_match(++fname, pattern))
+                       return 1;
+       return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
+#ifdef LIBSA_LFS
+/*
+ * Find an inode's block.  Look it up in the ifile.  Whee!
+ */
+static int
+find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct fs *fs = fp->f_fs;
+       daddr_t ifileent_blkno;
+       char *ent_in_buf;
+       size_t buf_after_ent;
+       int rc;
+
+       rc = read_inode(fs->lfs_ifile, f);
+       if (rc)
+               return rc;
+
+       ifileent_blkno =
+           (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz;
+       fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize +
+           (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx);
+       rc = buf_read_file(f, &ent_in_buf, &buf_after_ent);
+       if (rc)
+               return rc;
+       /* make sure something's not badly wrong, but don't panic. */
+       if (buf_after_ent < sizeof (IFILE_Vx))
+               return EINVAL;
+
+       *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr);
+       if (*isp == LFS_UNUSED_DADDR)   /* again, something badly wrong */
+               return EINVAL;
+       return 0;
+}
+#endif
+
+/*
+ * Read a new inode into a file structure.
+ */
+static int
+read_inode(ino32_t inumber, struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct fs *fs = fp->f_fs;
+       char *buf;
+       size_t rsize;
+       int rc;
+       daddr_t inode_sector;
+#ifdef LIBSA_LFS
+       struct ufs_dinode *dip;
+       int cnt;
+#endif
+
+#ifdef LIBSA_LFS
+       if (inumber == fs->lfs_ifile)
+               inode_sector = FSBTODB(fs, fs->lfs_idaddr);
+       else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
+               return rc;
+#else
+       inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
+#endif
+
+       /*
+        * Read inode and save it.
+        */
+       buf = fp->f_buf;
+       twiddle();
+       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+           inode_sector, fs->fs_bsize, buf, &rsize);
+       if (rc)
+               return rc;
+       if (rsize != fs->fs_bsize)
+               return EIO;
+
+#ifdef LIBSA_LFS
+       cnt = INOPBx(fs);
+       dip = (struct ufs_dinode *)buf + (cnt - 1);
+       for (; dip->di_inumber != inumber; --dip) {
+               /* kernel code panics, but boot blocks which panic are Bad. */
+               if (--cnt == 0)
+                       return EINVAL;
+       }
+       fp->f_di = *dip;
+#else
+       fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
+#endif
+
+       /*
+        * Clear out the old buffers
+        */
+       fp->f_ind_cache_block = ~0;
+       fp->f_buf_blkno = -1;
+       return rc;
+}
+
+/*
+ * Given an offset in a file, find the disk block number that
+ * contains that block.
+ */
+static int
+block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct fs *fs = fp->f_fs;
+       uint level;
+       indp_t ind_cache;
+       indp_t ind_block_num;
+       size_t rsize;
+       int rc;
+       indp_t *buf = (void *)fp->f_buf;
+
+       /*
+        * Index structure of an inode:
+        *
+        * di_db[0..NDADDR-1]   hold block numbers for blocks
+        *                      0..NDADDR-1
+        *
+        * di_ib[0]             index block 0 is the single indirect block
+        *                      holds block numbers for blocks
+        *                      NDADDR .. NDADDR + NINDIR(fs)-1
+        *
+        * di_ib[1]             index block 1 is the double indirect block
+        *                      holds block numbers for INDEX blocks for blocks
+        *                      NDADDR + NINDIR(fs) ..
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
+        *
+        * di_ib[2]             index block 2 is the triple indirect block
+        *                      holds block numbers for double-indirect
+        *                      blocks for blocks
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
+        *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2
+        *                              + NINDIR(fs)**3 - 1
+        */
+
+       if (file_block < NDADDR) {
+               /* Direct block. */
+               *disk_block_p = fp->f_di.di_db[file_block];
+               return 0;
+       }
+
+       file_block -= NDADDR;
+
+       ind_cache = file_block >> LN2_IND_CACHE_SZ;
+       if (ind_cache == fp->f_ind_cache_block) {
+               *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
+               return 0;
+       }
+
+       for (level = 0;;) {
+               level += fp->f_nishift;
+               if (file_block < (indp_t)1 << level)
+                       break;
+               if (level > NIADDR * fp->f_nishift)
+                       /* Block number too high */
+                       return EFBIG;
+               file_block -= (indp_t)1 << level;
+       }
+
+       ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
+
+       for (;;) {
+               level -= fp->f_nishift;
+               if (ind_block_num == 0) {
+                       *disk_block_p = 0;      /* missing */
+                       return 0;
+               }
+
+               twiddle();
+               /*
+                * If we were feeling brave, we could work out the number
+                * of the disk sector and read a single disk sector instead
+                * of a filesystem block.
+                * However we don't do this very often anyway...
+                */
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                       FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
+                       buf, &rsize);
+               if (rc)
+                       return rc;
+               if (rsize != fs->fs_bsize)
+                       return EIO;
+               ind_block_num = buf[file_block >> level];
+               if (level == 0)
+                       break;
+               file_block &= (1 << level) - 1;
+       }
+
+       /* Save the part of the block that contains this sector */
+       memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
+           IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
+       fp->f_ind_cache_block = ind_cache;
+
+       *disk_block_p = ind_block_num;
+
+       return 0;
+}
+
+/*
+ * Read a portion of a file into an internal buffer.
+ * Return the location in the buffer and the amount in the buffer.
+ */
+static int
+buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct fs *fs = fp->f_fs;
+       long off;
+       indp_t file_block;
+       indp_t disk_block;
+       size_t block_size;
+       int rc;
+
+       off = blkoff(fs, fp->f_seekp);
+       file_block = lblkno(fs, fp->f_seekp);
+#ifdef LIBSA_LFS
+       block_size = dblksize(fs, &fp->f_di, file_block);
+#else
+       block_size = sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
+#endif
+
+       if (file_block != fp->f_buf_blkno) {
+               rc = block_map(f, file_block, &disk_block);
+               if (rc)
+                       return rc;
+
+               if (disk_block == 0) {
+                       memset(fp->f_buf, 0, block_size);
+                       fp->f_buf_size = block_size;
+               } else {
+                       twiddle();
+                       rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                               FSBTODB(fs, disk_block),
+                               block_size, fp->f_buf, &fp->f_buf_size);
+                       if (rc)
+                               return rc;
+               }
+
+               fp->f_buf_blkno = file_block;
+       }
+
+       /*
+        * Return address of byte in buffer corresponding to
+        * offset, and size of remainder of buffer after that
+        * byte.
+        */
+       *buf_p = fp->f_buf + off;
+       *size_p = block_size - off;
+
+       /*
+        * But truncate buffer at end of file.
+        */
+       if (*size_p > fp->f_di.di_size - fp->f_seekp)
+               *size_p = fp->f_di.di_size - fp->f_seekp;
+
+       return 0;
+}
+
+/*
+ * Search a directory for a name and return its
+ * inode number.
+ */
+static int
+search_directory(const char *name, int length, struct open_file *f,
+       ino32_t *inumber_p)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       struct direct *dp;
+       struct direct *edp;
+       char *buf;
+       size_t buf_size;
+       int namlen;
+       int rc;
+
+       fp->f_seekp = 0;
+       while (fp->f_seekp < (off_t)fp->f_di.di_size) {
+               rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       return rc;
+
+               dp = (struct direct *)buf;
+               edp = (struct direct *)(buf + buf_size);
+               for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
+                       if (dp->d_reclen <= 0)
+                               break;
+                       if (dp->d_ino == (ino32_t)0)
+                               continue;
+#if BYTE_ORDER == LITTLE_ENDIAN
+                       if (fp->f_fs->fs_maxsymlinklen <= 0)
+                               namlen = dp->d_type;
+                       else
+#endif
+                               namlen = dp->d_namlen;
+                       if (namlen == length &&
+                           !memcmp(name, dp->d_name, length)) {
+                               /* found entry */
+                               *inumber_p = dp->d_ino;
+                               return 0;
+                       }
+               }
+               fp->f_seekp += buf_size;
+       }
+       return ENOENT;
+}
+
+#ifdef LIBSA_FFSv2
+
+daddr_t sblock_try[] = SBLOCKSEARCH;
+
+static int
+ffs_find_superblock(struct open_file *f, struct fs *fs)
+{
+       int i, rc;
+       size_t buf_size;
+
+       for (i = 0; sblock_try[i] != -1; i++) {
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                   sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
+               if (rc != 0 || buf_size != SBLOCKSIZE)
+                       return rc;
+               if (fs->fs_sblockloc != sblock_try[i])
+                       /* an alternate superblock - try again */
+                       continue;
+               if (fs->fs_magic == FS_UFS2_MAGIC) {
+                       return 0;
+               }
+       }
+       return EINVAL;
+}
+
+#endif
+
+/*
+ * Open a file.
+ */
+__compactcall int
+ufs_open(const char *path, struct open_file *f)
+{
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       const char *cp, *ncp;
+       int c;
+#endif
+       ino32_t inumber;
+       struct file *fp;
+       struct fs *fs;
+       int rc;
+#ifndef LIBSA_NO_FS_SYMLINK
+       ino32_t parent_inumber;
+       int nlinks = 0;
+       char namebuf[MAXPATHLEN+1];
+       char *buf;
+#endif
+
+       /* allocate file system specific data structure */
+       fp = alloc(sizeof(struct file));
+       memset(fp, 0, sizeof(struct file));
+       f->f_fsdata = (void *)fp;
+
+       /* allocate space and read super block */
+       fs = alloc(SBLOCKSIZE);
+       fp->f_fs = fs;
+       twiddle();
+
+#ifdef LIBSA_FFSv2
+       rc = ffs_find_superblock(f, fs);
+       if (rc)
+               goto out;
+#else
+       {
+               size_t buf_size;
+               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                       SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
+               if (rc)
+                       goto out;
+               if (buf_size != SBLOCKSIZE ||
+#ifdef LIBSA_FFS
+                   fs->lfs_version != REQUIRED_LFS_VERSION ||
+#endif
+                   fs->fs_magic != FS_MAGIC) {
+                       rc = EINVAL;
+                       goto out;
+               }
+       }
+#if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
+       /*
+        * XXX  We should check the second superblock and use the eldest
+        *      of the two.  See comments near the top of lfs_mountfs()
+        *      in sys/ufs/lfs/lfs_vfsops.c.
+        *      This may need a LIBSA_LFS_SMALL check as well.
+        */
+#endif
+#endif
+
+#ifdef LIBSA_FFSv1
+       ffs_oldfscompat(fs);
+#endif
+
+       if (fs->fs_bsize > MAXBSIZE ||
+           (size_t)fs->fs_bsize < sizeof(struct fs)) {
+               rc = EINVAL;
+               goto out;
+       }
+
+       /*
+        * Calculate indirect block levels.
+        */
+       {
+               indp_t mult;
+               int ln2;
+
+               /*
+                * We note that the number of indirect blocks is always
+                * a power of 2.  This lets us use shifts and masks instead
+                * of divide and remainder and avoinds pulling in the
+                * 64bit division routine into the boot code.
+                */
+               mult = NINDIR(fs);
+#ifdef DEBUG
+               if (mult & (mult - 1)) {
+                       /* Hummm was't a power of 2 */
+                       rc = EINVAL;
+                       goto out;
+               }
+#endif
+               for (ln2 = 0; mult != 1; ln2++)
+                       mult >>= 1;
+
+               fp->f_nishift = ln2;
+       }
+
+       /* alloc a block sized buffer used for all fs transfers */
+       fp->f_buf = alloc(fs->fs_bsize);
+       inumber = ROOTINO;
+       if ((rc = read_inode(inumber, f)) != 0)
+               goto out;
+
+#ifndef LIBSA_FS_SINGLECOMPONENT
+       cp = path;
+       while (*cp) {
+
+               /*
+                * Remove extra separators
+                */
+               while (*cp == '/')
+                       cp++;
+               if (*cp == '\0')
+                       break;
+
+               /*
+                * Check that current node is a directory.
+                */
+               if ((fp->f_di.di_mode & IFMT) != IFDIR) {
+                       rc = ENOTDIR;
+                       goto out;
+               }
+
+               /*
+                * Get next component of path name.
+                */
+               ncp = cp;
+               while ((c = *cp) != '\0' && c != '/')
+                       cp++;
+
+               /*
+                * Look up component in current directory.
+                * Save directory inumber in case we find a
+                * symbolic link.
+                */
+#ifndef LIBSA_NO_FS_SYMLINK
+               parent_inumber = inumber;
+#endif
+               rc = search_directory(ncp, cp - ncp, f, &inumber);
+               if (rc)
+                       goto out;
+
+               /*
+                * Open next component.
+                */
+               if ((rc = read_inode(inumber, f)) != 0)
+                       goto out;
+
+#ifndef LIBSA_NO_FS_SYMLINK
+               /*
+                * Check for symbolic link.
+                */
+               if ((fp->f_di.di_mode & IFMT) == IFLNK) {
+                       int link_len = fp->f_di.di_size;
+                       int len;
+
+                       len = strlen(cp);
+
+                       if (link_len + len > MAXPATHLEN ||
+                           ++nlinks > MAXSYMLINKS) {
+                               rc = ENOENT;
+                               goto out;
+                       }
+
+                       memmove(&namebuf[link_len], cp, len + 1);
+
+                       if (link_len < fs->fs_maxsymlinklen) {
+                               memcpy(namebuf, fp->f_di.di_db, link_len);
+                       } else {
+                               /*
+                                * Read file for symbolic link
+                                */
+                               size_t buf_size;
+                               indp_t  disk_block;
+
+                               buf = fp->f_buf;
+                               rc = block_map(f, (indp_t)0, &disk_block);
+                               if (rc)
+                                       goto out;
+
+                               twiddle();
+                               rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
+                                       F_READ, FSBTODB(fs, disk_block),
+                                       fs->fs_bsize, buf, &buf_size);
+                               if (rc)
+                                       goto out;
+
+                               memcpy(namebuf, buf, link_len);
+                       }
+
+                       /*
+                        * If relative pathname, restart at parent directory.
+                        * If absolute pathname, restart at root.
+                        */
+                       cp = namebuf;
+                       if (*cp != '/')
+                               inumber = parent_inumber;
+                       else
+                               inumber = (ino32_t)ROOTINO;
+
+                       if ((rc = read_inode(inumber, f)) != 0)
+                               goto out;
+               }
+#endif /* !LIBSA_NO_FS_SYMLINK */
+       }
+
+       /*
+        * Found terminal component.
+        */
+       rc = 0;
+
+#else /* !LIBSA_FS_SINGLECOMPONENT */
+
+       /* look up component in the current (root) directory */
+       rc = search_directory(path, strlen(path), f, &inumber);
+       if (rc)
+               goto out;
+
+       /* open it */
+       rc = read_inode(inumber, f);
+
+#endif /* !LIBSA_FS_SINGLECOMPONENT */
+
+       fp->f_seekp = 0;                /* reset seek pointer */
+
+out:
+       if (rc)
+               ufs_close(f);
+       else {
+#ifdef FSMOD
+               fsmod = FSMOD;
+#endif
+#ifdef FSMOD2
+               fsmod2 = FSMOD2;
+#endif
+       }
+       return rc;
+}
+
+__compactcall int
+ufs_close(struct open_file *f)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       f->f_fsdata = NULL;
+       if (fp == NULL)
+               return 0;
+
+       if (fp->f_buf)
+               dealloc(fp->f_buf, fp->f_fs->fs_bsize);
+       dealloc(fp->f_fs, SBLOCKSIZE);
+       dealloc(fp, sizeof(struct file));
+       return 0;
+}
+
+/*
+ * Copy a portion of a file into kernel memory.
+ * Cross block boundaries when necessary.
+ */
+__compactcall int
+ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       size_t csize;
+       char *buf;
+       size_t buf_size;
+       int rc = 0;
+       char *addr = start;
+
+       while (size != 0) {
+               if (fp->f_seekp >= (off_t)fp->f_di.di_size)
+                       break;
+
+               rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       break;
+
+               csize = size;
+               if (csize > buf_size)
+                       csize = buf_size;
+
+               memcpy(addr, buf, csize);
+
+               fp->f_seekp += csize;
+               addr += csize;
+               size -= csize;
+       }
+       if (resid)
+               *resid = size;
+       return rc;
+}
+
+/*
+ * Not implemented.
+ */
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+ufs_seek(struct open_file *f, off_t offset, int where)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       switch (where) {
+       case SEEK_SET:
+               fp->f_seekp = offset;
+               break;
+       case SEEK_CUR:
+               fp->f_seekp += offset;
+               break;
+       case SEEK_END:
+               fp->f_seekp = fp->f_di.di_size - offset;
+               break;
+       default:
+               return -1;
+       }
+       return fp->f_seekp;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+__compactcall int
+ufs_stat(struct open_file *f, struct stat *sb)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+
+       /* only important stuff */
+       memset(sb, 0, sizeof *sb);
+       sb->st_mode = fp->f_di.di_mode;
+       sb->st_uid = fp->f_di.di_uid;
+       sb->st_gid = fp->f_di.di_gid;
+       sb->st_size = fp->f_di.di_size;
+       return 0;
+}
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ufs_ls(struct open_file *f, const char *pattern)
+{
+       struct file *fp = (struct file *)f->f_fsdata;
+       char *buf;
+       size_t buf_size;
+       entry_t *names = 0, *n, **np;
+
+       fp->f_seekp = 0;
+       while (fp->f_seekp < (off_t)fp->f_di.di_size) {
+               struct direct  *dp, *edp;
+               int rc = buf_read_file(f, &buf, &buf_size);
+               if (rc)
+                       goto out;
+               /* some firmware might use block size larger than DEV_BSIZE */
+               if (buf_size < DIRBLKSIZ)
+                       goto out;
+
+               dp = (struct direct *)buf;
+               edp = (struct direct *)(buf + buf_size);
+
+               for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
+                       const char *t;
+                       if (dp->d_ino ==  0)
+                               continue;
+
+                       if (dp->d_type >= NELEM(typestr) ||
+                           !(t = typestr[dp->d_type])) {
+                               /*
+                                * This does not handle "old"
+                                * filesystems properly. On little
+                                * endian machines, we get a bogus
+                                * type name if the namlen matches a
+                                * valid type identifier. We could
+                                * check if we read namlen "0" and
+                                * handle this case specially, if
+                                * there were a pressing need...
+                                */
+                               printf("bad dir entry\n");
+                               goto out;
+                       }
+                       if (pattern && !fn_match(dp->d_name, pattern))
+                               continue;
+                       n = alloc(sizeof *n + strlen(dp->d_name));
+                       if (!n) {
+                               printf("%d: %s (%s)\n",
+                                       dp->d_ino, dp->d_name, t);
+                               continue;
+                       }
+                       n->e_ino = dp->d_ino;
+                       n->e_type = dp->d_type;
+                       strcpy(n->e_name, dp->d_name);
+                       for (np = &names; *np; np = &(*np)->e_next) {
+                               if (strcmp(n->e_name, (*np)->e_name) < 0)
+                                       break;
+                       }
+                       n->e_next = *np;
+                       *np = n;
+               }
+               fp->f_seekp += buf_size;
+       }
+
+       if (names) {
+               entry_t *p_names = names;
+               do {
+                       n = p_names;
+                       printf("%d: %s (%s)\n",
+                               n->e_ino, n->e_name, typestr[n->e_type]);
+                       p_names = n->e_next;
+               } while (p_names);
+       } else {
+               printf("not found\n");
+       }
+out:
+       if (names) {
+               do {
+                       n = names;
+                       names = n->e_next;
+                       dealloc(n, 0);
+               } while (names);
+       }
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
+#ifdef LIBSA_FFSv1
+/*
+ * Sanity checks for old file systems.
+ *
+ * XXX - goes away some day.
+ * Stripped of stuff libsa doesn't need.....
+ */
+static void
+ffs_oldfscompat(struct fs *fs)
+{
+
+#ifdef COMPAT_UFS
+       /*
+        * Newer Solaris versions have a slightly incompatible
+        * superblock - so always calculate this values on the fly, which
+        * is good enough for libsa purposes
+        */
+       if (fs->fs_magic == FS_UFS1_MAGIC
+#ifndef COMPAT_SOLARIS_UFS
+           && fs->fs_old_inodefmt < FS_44INODEFMT
+#endif
+           ) {
+               fs->fs_qbmask = ~fs->fs_bmask;
+               fs->fs_qfmask = ~fs->fs_fmask;
+       }
+#endif
+}
+#endif
diff --git a/sys/lib/libsa/ufs.h b/sys/lib/libsa/ufs.h
new file mode 100644 (file)
index 0000000..2f93ea9
--- /dev/null
@@ -0,0 +1,36 @@
+/*     $NetBSD: ufs.h,v 1.10 2011/12/25 06:09:08 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ufs.h       8.1 (Berkeley) 6/11/93
+ */
+
+FS_DEF(ufs);
+FS_DEF(ffsv1);
+FS_DEF(ffsv2);
diff --git a/sys/lib/libsa/ustarfs.c b/sys/lib/libsa/ustarfs.c
new file mode 100644 (file)
index 0000000..6dbe842
--- /dev/null
@@ -0,0 +1,560 @@
+/*     $NetBSD: ustarfs.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $     */
+
+/* [Notice revision 2.2]
+ * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc.
+ * All rights reserved.
+ *
+ * Author: Ross Harvey
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright and
+ *    author notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ * 4. This copyright will be assigned to The NetBSD Foundation on
+ *    1/1/2000 unless these terms (including possibly the assignment
+ *    date) are updated in writing by Avalon prior to the latest specified
+ *    assignment date.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ ******************************* USTAR FS *******************************
+ */
+
+/*
+ * Implement an ROFS with an 8K boot area followed by ustar-format data.
+ * The point: minimal FS overhead, and it's easy (well, `possible') to
+ * split files over multiple volumes.
+ *
+ * XXX - TODO LIST
+ * --- - ---- ----
+ * XXX - tag volume numbers and verify that the correct volume is
+ *       inserted after volume swaps.
+ *
+ * XXX - stop hardwiring FS metadata for floppies...embed it in a file,
+ *      file name, or something. (Remember __SYMDEF? :-)
+ *
+ * XXX Does not currently implement:
+ * XXX
+ * XXX LIBSA_NO_FS_CLOSE
+ * XXX LIBSA_NO_FS_SEEK
+ * XXX LIBSA_NO_FS_WRITE
+ * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?)
+ * XXX LIBSA_FS_SINGLECOMPONENT
+ */
+
+#ifdef _STANDALONE
+#include <lib/libkern/libkern.h>
+#else
+#include <string.h>
+#endif
+#include "stand.h"
+#include "ustarfs.h"
+
+#define        BBSIZE  8192
+#define        USTAR_NAME_BLOCK 512
+
+/*
+ * Virtual offset: relative to start of ustar archive
+ * Logical offset: volume-relative
+ * Physical offset: the usual meaning
+ */
+
+/* virtual offset to volume number */
+
+#define        vda2vn(_v,_volsize) ((_v) / (_volsize))
+
+/* conversions between the three different levels of disk addresses */
+
+#define        vda2lda(_v,_volsize) ((_v) % (_volsize))
+#define        lda2vda(_v,_volsize,_volnumber) ((_v) + (_volsize) * (_volnumber))
+
+#define        lda2pda(_lda) ((_lda) + ustarfs_mode_offset)
+#define        pda2lda(_pda) ((_pda) - ustarfs_mode_offset)
+/*
+ * Change this to off_t if you want to support big volumes. If we only use
+ * ustarfs on floppies it can stay int for libsa code density.
+ *
+ * It needs to be signed.
+ */
+typedef        int ustoffs;
+
+typedef struct ustar_struct {
+       char    ust_name[100],
+               ust_mode[8],
+               ust_uid[8],
+               ust_gid[8],
+               ust_size[12],
+               ust_misc[12 + 8 + 1 + 100],
+               ust_magic[6],
+       /* there is more, but we don't care */
+               ust_pad[1];     /* make it aligned */
+} ustar_t;
+
+/*
+ * We buffer one even cylinder of data...it's actually only really one
+ * cyl on a 1.44M floppy, but on other devices it's fast enough with any
+ * kind of block buffering, so we optimize for the slowest device.
+ */
+
+#ifndef USTAR_SECT_PER_CYL
+#define USTAR_SECT_PER_CYL     (18 * 2)
+#endif
+
+typedef struct ust_active_struct {
+       ustar_t uas_active;
+       char    uas_1cyl[USTAR_SECT_PER_CYL * 512];
+       ustoffs uas_volsize;            /* XXX this is hardwired now */
+       ustoffs uas_windowbase;         /* relative to volume 0 */
+       ustoffs uas_filestart;          /* relative to volume 0 */
+       ustoffs uas_fseek;              /* relative to file */
+       ustoffs uas_filesize;           /* relative to volume 0 */
+       int     uas_init_window;        /* data present in window */
+       int     uas_init_fs;            /* ust FS actually found */
+       int     uas_volzerosig;         /* ID volume 0 by signature */
+       int     uas_sigdone;            /* did sig already */
+       int     uas_offset;             /* amount of cylinder below lba 0 */
+} ust_active_t;
+
+static const char formatid[] = "USTARFS",
+                  metaname[] = "USTAR.volsize.";
+
+static const int ustarfs_mode_offset = BBSIZE;
+
+static int checksig(ust_active_t *);
+static int convert(const char *, int, int);
+static int get_volume(struct open_file *, int);
+static void setwindow(ust_active_t *, ustoffs, ustoffs);
+static int real_fs_cylinder_read(struct open_file *, ustoffs, int);
+static int ustarfs_cylinder_read(struct open_file *, ustoffs, int);
+static void ustarfs_sscanf(const char *, const char *, int *);
+static int read512block(struct open_file *, ustoffs, char block[512]);
+static int init_volzero_sig(struct open_file *);
+
+#ifdef HAVE_CHANGEDISK_HOOK
+/*
+ * Called when the next volume is prompted.
+ * Machine dependent code can eject the medium etc.
+ * The new medium must be ready when this hook returns.
+ */
+void changedisk_hook(struct open_file *);
+#endif
+
+static int
+convert(const char *f, int base, int fw)
+{
+       int     i, c, result = 0;
+
+       while(fw > 0 && *f == ' ') {
+               --fw;
+               ++f;
+       }
+       for(i = 0; i < fw; ++i) {
+               c = f[i];
+               if ('0' <= c && c < '0' + base) {
+                       c -= '0';
+                       result = result * base + c;
+               } else  break;
+       }
+       return result;
+}
+
+static void
+ustarfs_sscanf(const char *s, const char *f, int *xi)
+{
+
+       *xi = convert(s, 8, convert(f + 1, 10, 99));
+}
+
+static int
+ustarfs_cylinder_read(struct open_file *f, ustoffs seek2, int forcelabel)
+{
+       int i, e;
+
+       for (i = 0; i < 3; ++i) {
+               e = real_fs_cylinder_read(f, seek2, forcelabel);
+               if (e == 0)
+                       return 0;
+       }
+       return e;
+}
+
+static int
+real_fs_cylinder_read(struct open_file *f, ustoffs seek2, int forcelabel)
+{
+       int i;
+       int e = 0;      /* XXX work around gcc warning */
+       ustoffs lda;
+       char *xferbase;
+       ust_active_t *ustf;
+       size_t xferrqst, xfercount;
+
+       ustf = f->f_fsdata;
+       xferrqst = sizeof ustf->uas_1cyl;
+       xferbase = ustf->uas_1cyl;
+       lda = pda2lda(seek2);
+       if (lda < 0) {
+               lda = -lda;
+               ustf->uas_offset = lda;
+               /*
+                * don't read the label unless we have to. (Preserve
+                * sequential block access so tape boot works.)
+                */
+               if (!forcelabel) {
+                       memset(xferbase, 0, lda);
+                       xferrqst -= lda;
+                       xferbase += lda;
+                       seek2    += lda;
+               }
+       } else {
+               ustf->uas_offset = 0;
+       }
+       while(xferrqst > 0) {
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               for (i = 0; i < 3; ++i) {
+                       e = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+                           seek2 / 512, xferrqst, xferbase, &xfercount);
+                       if (e == 0)
+                               break;
+                       printf("@");
+               }
+               if (e)
+                       break;
+               if (xfercount != xferrqst)
+                       printf("Warning, unexpected short transfer %d/%d\n",
+                               (int)xfercount, (int)xferrqst);
+               xferrqst -= xfercount;
+               xferbase += xfercount;
+               seek2    += xfercount;
+       }
+       return e;
+}
+
+static int
+checksig(ust_active_t *ustf)
+{
+       int     i, rcs;
+
+       for(i = rcs = 0; i < (int)(sizeof ustf->uas_1cyl); ++i)
+               rcs += ustf->uas_1cyl[i];
+       return rcs;
+}
+
+static int
+get_volume(struct open_file *f, int vn)
+{
+       int     e, needvolume, havevolume;
+       ust_active_t *ustf;
+
+       ustf = f->f_fsdata;
+       havevolume = vda2vn(ustf->uas_windowbase, ustf->uas_volsize);
+       needvolume = vn;
+       while(havevolume != needvolume) {
+               printf("\nPlease ");
+               if (havevolume >= 0)
+                       printf("remove disk %d, ", havevolume + 1);
+               printf("insert disk %d, and press return...",
+                       needvolume + 1);
+#ifdef HAVE_CHANGEDISK_HOOK
+               changedisk_hook(f);
+#else
+               for (;;) {
+                       int c = getchar();
+                       if ((c == '\n') || (c == '\r'))
+                               break;
+               }
+#endif
+               printf("\n");
+               e = ustarfs_cylinder_read(f, 0, needvolume != 0);
+               if (e)
+                       return e;
+               if(strncmp(formatid, ustf->uas_1cyl, strlen(formatid))) {
+                       /* no magic, might be OK if we want volume 0 */
+                       if (ustf->uas_volzerosig == checksig(ustf)) {
+                               havevolume = 0;
+                               continue;
+                       }
+                       printf("Disk is not from the volume set?!\n");
+                       havevolume = -2;
+                       continue;
+               }
+               ustarfs_sscanf(ustf->uas_1cyl + strlen(formatid), "%9o",
+                       &havevolume);
+               --havevolume;
+       }
+       return 0;
+}
+
+static void
+setwindow(ust_active_t *ustf, ustoffs pda, ustoffs vda)
+{
+       ustf->uas_windowbase = lda2vda(pda2lda(pda), ustf->uas_volsize,
+                                       vda2vn(vda, ustf->uas_volsize))
+                            + ustf->uas_offset;
+       ustf->uas_init_window = 1;
+}
+
+static int
+read512block(struct open_file *f, ustoffs vda, char block[512])
+{
+       ustoffs pda;
+       ssize_t e;
+       int     dienow;
+       ust_active_t *ustf;
+
+       dienow = 0;
+       ustf = f->f_fsdata;
+
+       /*
+        * if (vda in window)
+        *      copy out and return data
+        * if (vda is on some other disk)
+        *      do disk swap
+        * get physical disk address
+        * round down to cylinder boundary
+        * read cylinder
+        * set window (in vda space) and try again
+        * [ there is an implicit assumption that windowbase always identifies
+        *    the current volume, even if initwindow == 0. This way, a
+        *    windowbase of 0 causes the initial volume to be disk 0 ]
+        */
+tryagain:
+       if(ustf->uas_init_window
+       && ustf->uas_windowbase <= vda && vda <
+          ustf->uas_windowbase +
+            (int)(sizeof ustf->uas_1cyl) - ustf->uas_offset) {
+               memcpy(block, ustf->uas_1cyl
+                               + (vda - ustf->uas_windowbase)
+                               + ustf->uas_offset, 512);
+               return 0;
+       }
+       if (dienow++)
+               panic("ustarfs read512block");
+       ustf->uas_init_window = 0;
+       e = get_volume(f, vda2vn(vda, ustf->uas_volsize));
+       if (e)
+               return e;
+       pda = lda2pda(vda2lda(vda, ustf->uas_volsize));
+       pda-= pda % sizeof ustf->uas_1cyl;
+       e = ustarfs_cylinder_read(f, pda, 0);
+       if (e)
+               return e;
+       setwindow(ustf, pda, vda);
+       goto tryagain;
+}
+
+static int
+init_volzero_sig(struct open_file *f)
+{
+       int e;
+       ust_active_t *ustf;
+
+       ustf = f->f_fsdata;
+       if (!ustf->uas_sigdone) {
+               e = ustarfs_cylinder_read(f, 0, 0);
+               if (e)
+                       return e;
+               ustf->uas_volzerosig = checksig(ustf);
+               setwindow(ustf, 0, 0);
+       }
+       return 0;
+}
+
+__compactcall int
+ustarfs_open(const char *path, struct open_file *f)
+{
+       ust_active_t *ustf;
+       ustoffs offset;
+       char    block[512];
+       int     filesize;
+       int     e, e2;
+       int     newvolblocks;
+
+       if (*path == '/')
+               ++path;
+       f->f_fsdata = ustf = alloc(sizeof *ustf);
+       memset(ustf, 0, sizeof *ustf);
+       offset = 0;
+       /* default to 2880 sector floppy */
+       ustf->uas_volsize = 80 * 2 * 18 * 512 - lda2pda(0);
+       ustf->uas_fseek = 0;
+       e = init_volzero_sig(f);
+       if (e)
+               return e;
+       e2 = EINVAL;
+       for(;;) {
+               ustf->uas_filestart = offset;
+               e = read512block(f, offset, block);
+               if (e)
+                       break;
+               memcpy(&ustf->uas_active, block, sizeof ustf->uas_active);
+               if(strncmp(ustf->uas_active.ust_magic, "ustar", 5)) {
+                       e = e2;
+                       break;
+               }
+               e2 = ENOENT;    /* it must be an actual ustarfs */
+               ustf->uas_init_fs = 1;
+               /* if volume metadata is found, use it */
+               if(strncmp(ustf->uas_active.ust_name, metaname,
+                   strlen(metaname)) == 0) {
+                       ustarfs_sscanf(ustf->uas_active.ust_name
+                               + strlen(metaname), "%99o", &newvolblocks);
+                       ustf->uas_volsize = newvolblocks * 512
+                                         - lda2pda(0);
+               }
+               ustarfs_sscanf(ustf->uas_active.ust_size,"%12o",&filesize);
+               if(strncmp(ustf->uas_active.ust_name, path,
+                   sizeof ustf->uas_active.ust_name) == 0) {
+                       ustf->uas_filesize = filesize;
+                       break;
+               }
+               offset += USTAR_NAME_BLOCK + filesize;
+               filesize %= 512;
+               if (filesize)
+                       offset += 512 - filesize;
+       }
+       if (e) {
+               dealloc(ustf, sizeof *ustf);
+               f->f_fsdata = 0;
+       }
+       return e;
+}
+
+#ifndef LIBSA_NO_FS_WRITE
+__compactcall int
+ustarfs_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+       return EROFS;
+}
+#endif /* !LIBSA_NO_FS_WRITE */
+
+#ifndef LIBSA_NO_FS_SEEK
+__compactcall off_t
+ustarfs_seek(struct open_file *f, off_t offs, int whence)
+{
+       ust_active_t *ustf;
+
+       ustf = f->f_fsdata;
+       switch (whence) {
+       case SEEK_SET:
+               ustf->uas_fseek = offs;
+               break;
+       case SEEK_CUR:
+               ustf->uas_fseek += offs;
+               break;
+       case SEEK_END:
+               ustf->uas_fseek = ustf->uas_filesize - offs;
+               break;
+       default:
+               return -1;
+       }
+       return ustf->uas_fseek;
+}
+#endif /* !LIBSA_NO_FS_SEEK */
+
+__compactcall int
+ustarfs_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+       ust_active_t *ustf;
+       int     e;
+       char    *space512;
+       int     blkoffs;
+       int     readoffs;
+       int     bufferoffset;
+       size_t  seg;
+       size_t  infile;
+       size_t  inbuffer;
+
+       e = 0;
+       space512 = alloc(512);
+       ustf = f->f_fsdata;
+       while(size != 0) {
+               if (ustf->uas_fseek >= ustf->uas_filesize)
+                       break;
+               bufferoffset = ustf->uas_fseek % 512;
+               blkoffs  = ustf->uas_fseek - bufferoffset;
+               readoffs = ustf->uas_filestart + 512 + blkoffs;
+               e = read512block(f, readoffs, space512);
+               if (e)
+                       break;
+               seg = size;
+               inbuffer = 512 - bufferoffset;
+               if (inbuffer < seg)
+                       seg = inbuffer;
+               infile = ustf->uas_filesize - ustf->uas_fseek;
+               if (infile < seg)
+                       seg = infile;
+               memcpy(start, space512 + bufferoffset, seg);
+               ustf->uas_fseek += seg;
+               start = (char *)start + seg;
+               size -= seg;
+       }
+       if (resid)
+               *resid = size;
+       dealloc(space512, 512);
+       return e;
+}
+
+__compactcall int
+ustarfs_stat(struct open_file *f, struct stat *sb)
+{
+       int     mode, uid, gid;
+       ust_active_t *ustf;
+
+       if (f == NULL)
+               return EINVAL;
+       ustf = f->f_fsdata;
+       memset(sb, 0, sizeof *sb);
+       ustarfs_sscanf(ustf->uas_active.ust_mode, "%8o", &mode);
+       ustarfs_sscanf(ustf->uas_active.ust_uid, "%8o", &uid);
+       ustarfs_sscanf(ustf->uas_active.ust_gid, "%8o", &gid);
+       sb->st_mode = mode;
+       sb->st_uid  = uid;
+       sb->st_gid  = gid;
+       sb->st_size = ustf->uas_filesize;
+       return 0;
+}
+
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ustarfs_ls(struct open_file *f, const char *pattern)
+{
+       printf("Currently ls command is unsupported by ustarfs\n");
+       return;
+}
+#endif
+
+#ifndef LIBSA_NO_FS_CLOSE
+__compactcall int
+ustarfs_close(struct open_file *f)
+{
+       if (f == NULL || f->f_fsdata == NULL)
+               return EINVAL;
+       dealloc(f->f_fsdata, sizeof(ust_active_t));
+       f->f_fsdata = 0;
+       return 0;
+}
+#endif /* !LIBSA_NO_FS_CLOSE */
diff --git a/sys/lib/libsa/ustarfs.h b/sys/lib/libsa/ustarfs.h
new file mode 100644 (file)
index 0000000..1a0e86f
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $NetBSD: ustarfs.h,v 1.3 2005/12/11 12:24:46 christos Exp $     */
+
+/* [Notice revision 2.2]
+ * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc.
+ * All rights reserved.
+ *
+ * Author: Ross Harvey
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright and
+ *    author notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ * 4. This copyright will be assigned to The NetBSD Foundation on
+ *    1/1/2000 unless these terms (including possibly the assignment
+ *    date) are updated in writing by Avalon prior to the latest specified
+ *    assignment date.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+FS_DEF(ustarfs);
diff --git a/sys/lib/libsa/vsprintf.c b/sys/lib/libsa/vsprintf.c
new file mode 100644 (file)
index 0000000..e7d3c42
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $NetBSD: vsprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)printf.c    8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "stand.h"
+
+int
+vsprintf(char *buf, const char *fmt, va_list ap)
+{
+
+       return vsnprintf(buf, -(size_t)buf, fmt, ap);
+}
diff --git a/sys/lib/libsa/write.c b/sys/lib/libsa/write.c
new file mode 100644 (file)
index 0000000..a1e6e0f
--- /dev/null
@@ -0,0 +1,96 @@
+/*     $NetBSD: write.c,v 1.15 2007/12/02 04:59:26 tsutsui Exp $       */
+
+/*-
+ * Copyright (c) 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)write.c     8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Author: Alessandro Forin
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include "stand.h"
+
+ssize_t
+write(int fd, const void *destp, size_t bcount)
+{
+       struct open_file *f = &files[fd];
+       size_t resid;
+       void *dest = __UNCONST(destp);
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+       if ((unsigned int)fd >= SOPEN_MAX || !(f->f_flags & F_WRITE)) {
+               errno = EBADF;
+               return -1;
+       }
+#endif
+#if !defined(LIBSA_NO_RAW_ACCESS)
+       if (f->f_flags & F_RAW) {
+#if !defined(LIBSA_NO_TWIDDLE)
+               twiddle();
+#endif
+               errno = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_WRITE,
+                       btodb(f->f_offset), bcount, dest, &resid);
+               if (errno)
+                       return -1;
+               f->f_offset += resid;
+               return resid;
+       }
+#endif
+       resid = bcount;
+       if ((errno = FS_WRITE(f->f_ops)(f, dest, bcount, &resid)))
+               return -1;
+       return 0;
+}
index 251ba7adaa1ad9fbc44665be19342fcd6e292e9a..e4830d47f720031ecc36b4eda7345ef41c7ab3dc 100644 (file)
@@ -42,3 +42,8 @@ usr.bin/bzip2recover  src/usr.bin/bzip2recover
 libexec/makewhatis     src/libexec/makewhatis
 dist/bzip2             src/dist/bzip2
 share/zoneinfo         src/share/zoneinfo
+sys/arch/i386/stand/bootxx     src/sys/arch/i386/stand/bootxx
+sys/arch/i386/stand/boot       src/sys/arch/i386/stand/boot
+sys/arch/i386/stand/lib                src/sys/arch/i386/stand/lib
+sys/lib/libsa          src/sys/lib/libsa
+sys/lib/libz           src/sys/lib/libz