-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 \
--- /dev/null
+.\" $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.
-.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).
--- /dev/null
+# $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
--- /dev/null
+# $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>
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $
+
+PROG= boot
+
+.include <../Makefile.boot>
--- /dev/null
+/* $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");
+}
+
--- /dev/null
+/* $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);
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 *);
--- /dev/null
+$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.
--- /dev/null
+# $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
--- /dev/null
+# $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>
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2010/09/11 13:06:37 tsutsui Exp $
+
+FS=ext2fs
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=ffsv1
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=ffsv2
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $
+
+FS=lfsv1
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $
+
+FS=lfsv2
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $NetBSD$
+
+PROG=bootxx_minixfs3
+FS=minixfs3
+CPPFLAGS=-DBOOT_FROM_MINIXFS3 -DTERSE_ERROR
+
+.include <../Makefile.bootxx>
--- /dev/null
+# $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>
--- /dev/null
+# $NetBSD: Makefile,v 1.3 2009/11/18 21:02:16 dsl Exp $
+
+FS=ustarfs
+
+BOOTXX_SECTORS=16
+
+.include <../Makefile.bootxx>
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+# $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}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
--- /dev/null
+/* $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
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
+
--- /dev/null
+/* $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
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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));
+}
--- /dev/null
+/* $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));
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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
--- /dev/null
+/* $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... */
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 *);
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+ }
+}
--- /dev/null
+/* $NetBSD: isadmavar.h,v 1.2 2008/12/14 17:03:43 christos Exp $ */
+
+void isa_dmacascade(int);
--- /dev/null
+/* $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 */
+}
--- /dev/null
+/* $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*);
--- /dev/null
+/* $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 *);
--- /dev/null
+/* $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);
+ }
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+## $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
+ }
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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? */
+};
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
--- /dev/null
+/* $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");
+}
--- /dev/null
+/* $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)))
--- /dev/null
+# $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}
--- /dev/null
+# $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"
--- /dev/null
+# $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
--- /dev/null
+/* $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)
+{
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+# $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}
--- /dev/null
+/* $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)
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+# $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
--- /dev/null
+/*-
+ * 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)
--- /dev/null
+# $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
--- /dev/null
+/* $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 */
--- /dev/null
+/* $NetBSD: memcpy.S,v 1.1 2002/06/06 20:03:38 fredette Exp $ */
+
+#define MEMCPY
+#include "bcopy.S"
--- /dev/null
+/* $NetBSD: memmove.S,v 1.1 2002/06/06 20:03:38 fredette Exp $ */
+
+#define MEMMOVE
+#include "bcopy.S"
--- /dev/null
+; $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
--- /dev/null
+/* $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 ;
--- /dev/null
+/* $NetBSD: spcopy.S,v 1.1 2002/06/06 20:03:39 fredette Exp $ */
+
+#define SPCOPY
+#include "bcopy.S"
--- /dev/null
+# $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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)
--- /dev/null
+/* $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)
--- /dev/null
+/* $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)
--- /dev/null
+.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
--- /dev/null
+.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
--- /dev/null
+/* $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"
--- /dev/null
+/* $NetBSD: memcpy.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */
+
+#include <machine/asm.h>
+
--- /dev/null
+.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
--- /dev/null
+.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
--- /dev/null
+/* $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"
--- /dev/null
+.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
--- /dev/null
+.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
--- /dev/null
+.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
--- /dev/null
+.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
--- /dev/null
+/* $NetBSD: DEFS.h,v 1.4 1999/11/11 01:32:10 thorpej Exp $ */
+
+#include <machine/asm.h>
--- /dev/null
+# $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+/*-
+ * 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)
--- /dev/null
+/* $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
--- /dev/null
+/* $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");
+}
--- /dev/null
+# $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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)
--- /dev/null
+/* $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)
--- /dev/null
+/* $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)
--- /dev/null
+/* $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)
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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}
--- /dev/null
+/*
+ * 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')
--- /dev/null
+/* $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
--- /dev/null
+/* $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>
+
--- /dev/null
+# $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}
--- /dev/null
+/* $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')
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+# $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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));
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
+ }
+};
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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_ */
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+ }
+ }
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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 );
+
+}
+
--- /dev/null
+/* $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
+
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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
+
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 *);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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_ */
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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;
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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*/
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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];
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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*/
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
--- /dev/null
+/* $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"
--- /dev/null
+/* $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"
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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, ¬e, 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, ¬e.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) */
--- /dev/null
+/* $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"
--- /dev/null
+/* $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) */
--- /dev/null
+/* $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"
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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;
+ }
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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
--- /dev/null
+/* $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 *);
--- /dev/null
+/* $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;
+};
--- /dev/null
+/* $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
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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*/
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/*-
+ * 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);*/
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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) /* */
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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_ */
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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();
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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');
+ }
+}
--- /dev/null
+/* $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;
+}
--- /dev/null
+/* $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
--- /dev/null
+/* $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);
--- /dev/null
+/* $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 */
--- /dev/null
+/* $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);
--- /dev/null
+/* $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);
+}
--- /dev/null
+/* $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;
+}
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