From: Evgeniy Ivanov Date: Mon, 9 Jan 2012 14:07:58 +0000 (+0400) Subject: Initial import of libsa, libkern, bootxx, boot. X-Git-Tag: v3.2.0~79 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=58a2b0008e28f606a7f7f5faaeaba4faac57a1ea;p=minix.git Initial import of libsa, libkern, bootxx, boot. --- diff --git a/man/man5/Makefile b/man/man5/Makefile index 27ace22c2..5378f2af6 100644 --- a/man/man5/Makefile +++ b/man/man5/Makefile @@ -1,4 +1,4 @@ -MAN= configfile.5 crontab.5 dhcp.conf.5 dir.5 ethers.5 \ +MAN= boot.cfg.5 configfile.5 crontab.5 dhcp.conf.5 dir.5 ethers.5 \ fstab.5 hosts.5 httpd.conf.5 http_status.5 keymap.5 \ passwd.5 resolv.conf.5 resolver.5 rhosts.5 statvfs.5 serv.access.5 \ system.conf.5 syslog.conf.5 termcap.5 ttytab.5 TZ.5 tzfile.5 utmp.5 \ diff --git a/man/man5/boot.cfg.5 b/man/man5/boot.cfg.5 new file mode 100644 index 000000000..119ce33a9 --- /dev/null +++ b/man/man5/boot.cfg.5 @@ -0,0 +1,247 @@ +.\" $NetBSD: boot.cfg.5,v 1.24 2011/11/28 09:38:45 wiz Exp $ +.\" +.\" Copyright (c) 2007 Stephen Borrill +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd November 28, 2011 +.Dt BOOT.CFG 5 +.Os +.Sh NAME +.Nm boot.cfg +.Nd configuration file for /boot +.Sh DESCRIPTION +The file +.Pa /boot.cfg +is used to alter the behaviour of the standard boot loader described in +.Xr boot 8 . +Configuration changes include setting the timeout, choosing a console device, +altering the banner text and displaying a menu allowing boot commands to be +easily chosen. +If a +.Nm +file is not present, the system will boot as normal. +.Ss FILE FORMAT +The format of the file is a series of lines containing keyword/value pairs +separated by an equals sign +.Pq Sq = . +There should be no whitespace surrounding the equals sign. +Lines beginning with a hash +.Pq Sq # +are comments and will be ignored. +.Pp +Some keywords can be present multiple times in the file to define additional +items. +Such keywords are noted below. +.Pp +.Bl -tag -width timeout +.It Sy banner +(may be present multiple times) +The text from banner lines is displayed instead of the standard welcome text +by the boot loader. +Up to 10 lines can be defined. +No special character sequences are recognised, so to specify a blank line, a +banner line with no value should be given. +.It Sy clear +If nonzero, clear the screen before printing the banner. +If zero, do not clear the screen (the default). +.It Sy consdev +Changes the console device to that specified in the value. +Valid values are any of those that could be specified at the normal boot +prompt with the consdev command. +.It Sy default +Used to specify the default menu item which will be chosen in the case of +Return being pressed or the timeout timer reaching zero. +The value is the number of the menu item as displayed. +As described above, the menu items are counted from 1 in the order listed in +.Nm . +If not specified, the default value will be option 1, i.e. the first item. +.It Sy format +Changes how the menu options are displayed. +Should be set to one of +.Sq a +for automatic, +.Sq l +for letters and +.Sq n +for numbers. +If set to automatic (the default), menu options will be displayed numerically +unless there are more than 9 options and the timeout is greater than zero. +If there are more than 9 options with a timeout greater than zero and +the format is set to number, only the first 9 options will be available. +.It Sy load +Used to load kernel modules, which will be passed on to the kernel for +initialization during early boot. +The argument is either the complete path and file name of the module to be +loaded, or a symbolic module name. +When the argument is not an absolute path, the boot loader will first +attempt to load +.Pa /stand/\*[Lt]machine\*[Gt]/\*[Lt]kernel_version\*[Gt]/modules/\*[Lt]name\*[Gt]/\*[Lt]name\*[Gt].kmod . +If that file does not exist, it will then attempt to load +.Pa /\*[Lt]name\*[Gt] . +May be used as many times as needed. +.It Sy menu +(may be present multiple times) +Used to define a menu item to be displayed to the end-user at boot time +which allows a series of boot commands to be run without further typing. +The value consists of the required menu text, followed by a colon +.Pq Sq \&: +and then the desired command(s). +Multiple commands can be specified separated by a semi-colon. +If the specified menu text is empty +(the colon appears immediately after the equals sign), +then the displayed menu text is the same as the command. +For example: +.Bd -literal +menu=Boot normally:boot +menu=Boot single-user:boot -s +menu=Boot with module foo:load /foo.kmod;boot +menu=Boot with serial console:consdev com0;boot +menu=:boot hd1a:netbsd -as +.Ed +.Pp +Each menu item will be prefixed by an ascending number when displayed, +i.e. the order in the +.Nm +file is important. +.Pp +Each command is executed just as though the user had typed it in +and so can be any valid command that would be accepted at the +normal boot prompt. +In addition, +.Dq Ic prompt +can be used to drop to the normal boot prompt. +.It Sy timeout +If the value is greater than zero, this specifies the time in seconds +that the boot loader will wait for the end-user to choose a menu item. +During the countdown period, they may press Return to choose the default +option or press a number key corresponding to a menu option. +If any other key is pressed, the countdown will stop and the user will be +prompted to choose a menu option with no further time limit. +If the timeout value is set to zero, the default option will be booted +immediately. +If the timeout value is negative or is not a number, there will be no +time limit for the user to choose an option. +.It Sy userconf +Passes a +.Xr userconf 4 +command to the kernel at boot time . +.It Sy rndseed +Takes the path to a random-seed file as written by the +.Fl S +flag to +.Xr rndctl 8 +as an argument. +This file is used to seed the kernel entropy pool +.Xr rnd 9 +very early in kernel startup, so that high quality randomness is +available to all kernel modules. +This argument should be supplied +before any +.Dq Ic load +commands that may load executable modules. +.El +.Sh EXAMPLES +Here is an example +.Nm +file: +.Bd -literal -offset indent +banner=Welcome to NetBSD +banner================== +banner= +banner=Please choose an option from the following menu: +menu=Boot normally:boot +menu=Boot single-user:boot -s +menu=Boot from second disk:boot hd1a: +menu=Boot with module foo:load /foo.kmod;boot +menu=Boot with modules foo and bar:load /foo.kmod;load /bar.kmod;boot +menu=Boot Xen with 256MB for dom0:load /netbsd-XEN3_DOM0 console=pc;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M +menu=Boot Xen with 256MB for dom0 (serial):load /netbsd-XEN3_DOM0 console=com0;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M console=com1 com1=115200,8n1 +menu=Boot Xen with dom0 in single-user mode:load /netbsd-XEN3_DOM0 -s;multiboot /usr/pkg/xen3-kernel/xen.gz dom0_mem=256M +menu=Go to command line (advanced users only):prompt +clear=1 +timeout=-1 +default=1 +userconf disable ehci* +# Always load ramdisk module +load=/miniroot.kmod +.Ed +.Pp +N.B. Xen counts serial ports from com1 upwards, but +.Nx +counts from com0, so the appropriate device name must be used. +Please see the Xen with serial console example above. +.Pp +This will clear the screen and display: +.Bd -literal -offset indent +Welcome to NetBSD +================= + +Please choose an option from the following menu: + + 1. Boot normally + 2. Boot single-user + 3. Boot from second disk + 4. Boot with module foo + 5. Boot with modules foo and bar + 6. Boot Xen with 256 MB for dom0 + 7. Boot Xen with 256 MB for dom0 (serial) + 8. Boot Xen with dom0 in single-user mode + 9. Go to command line (advanced users only) + +Option [1]: +.Ed +.Pp +It will then wait for the user to type 1, 2, 3, 4, 5, 6, 7, 8 or 9 followed by +Return. +Pressing Return by itself will run option 1. +There will be no timeout. +.Sh SEE ALSO +.Xr boot 8 , +.Xr boothowto 9 +.Sh HISTORY +The +.Nm +file appeared in +.Nx 5.0 . +.Sh AUTHORS +The +.Nm +extensions to +.Xr boot 8 +were written by +.An Stephen Borrill +.Aq sborrill@NetBSD.org . +.Sh BUGS +Support for +.Nm +is currently for +.Nx Ns /i386 +and +.Nx Ns /amd64 +only. +It is hoped that its use will be extended to other appropriate ports that +use the +.Xr boot 8 +interface. diff --git a/man/man8/boot.8 b/man/man8/boot.8 index 6512d10a2..e61c32469 100644 --- a/man/man8/boot.8 +++ b/man/man8/boot.8 @@ -1,524 +1,649 @@ -.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 - 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 +.Dq wd +devices at the bootloader level. +This is less a bug of the bootloader code than +a shortcoming of the PC architecture. +The default disk device's name printed in the starting message +is derived from the +.Dq type +field of the +.Nx +disklabel (if it is a hard disk). diff --git a/sys/arch/i386/stand/boot/Makefile b/sys/arch/i386/stand/boot/Makefile new file mode 100644 index 000000000..7334e220c --- /dev/null +++ b/sys/arch/i386/stand/boot/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.8 2010/05/27 06:58:13 dholland Exp $ + +SUBDIR= biosboot + +LIBOBJ= ${.OBJDIR} +.MAKEOVERRIDES+= LIBOBJ + +.include +.include + +cleandir distclean: .WAIT cleanlibdir + +cleanlibdir: + -rm -rf lib diff --git a/sys/arch/i386/stand/boot/Makefile.boot b/sys/arch/i386/stand/boot/Makefile.boot new file mode 100644 index 000000000..c6b4d7cce --- /dev/null +++ b/sys/arch/i386/stand/boot/Makefile.boot @@ -0,0 +1,171 @@ +# $NetBSD: Makefile.boot,v 1.56 2011/12/25 06:09:09 tsutsui Exp $ + +S= ${.CURDIR}/../../../../.. + +NOMAN= +PROG?= boot +NEWVERSWHAT?= "BIOS Boot" +VERSIONFILE?= ${.CURDIR}/../version + +AFLAGS.biosboot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} + +SOURCES?= biosboot.S boot2.c conf.c devopen.c exec.c +SRCS= ${SOURCES} +.if !make(depend) +SRCS+= vers.c +.endif + +PIE_CFLAGS= +PIE_AFLAGS= +PIE_LDFLAGS= + +.include + +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 diff --git a/sys/arch/i386/stand/boot/biosboot.S b/sys/arch/i386/stand/boot/biosboot.S new file mode 100644 index 000000000..0c3033c7a --- /dev/null +++ b/sys/arch/i386/stand/boot/biosboot.S @@ -0,0 +1,149 @@ +/* $NetBSD: biosboot.S,v 1.8 2011/01/05 23:13:01 jakllsch Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +/* + * 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_start + 0x80 /* space for patchable variables */ +boot_start_1: + +#if 0 + /* Allow for boot_start not being %cs:0 */ + call 2f +2: pop %cx + sub $2b, %cx /* %ax is offset */ + test $0xf, %cx /* check code seg aligned */ + jz 3f + lret /* not playing if not */ +3: mov %cs, %ax + shr $4, %cx + add %cx, %ax /* segment staring at boot_start */ + push %ax + push $4f + lret +4: +#endif + + mov %cs, %ax + mov %ax, %es + + movl %ecx, %ebp /* move LBA out of the way */ + + /* Grab boot_params patched into bootxx by installboot */ + cmpl $X86_BOOT_MAGIC_1,-4(%si) /* sanity check ptr */ + jne 2f + mov $boot_params, %di + movl (%si),%ecx + cmp $boot_start_1 - boot_params, %cx + jbe 1f + mov $boot_start_1 - boot_params, %cx +1: cld + rep + movsb +2: + + mov %ax, %ds + movl $_end, %eax /* top of bss */ + shr $4, %eax /* as a segment */ + add $0x1001, %ax /* and + 64k */ + mov %ax, %ss /* for stack */ + mov $0xfffc, %sp /* %sp at top of it */ + + call gdt_fixup + + calll real_to_prot + .code32 + + movl $_end, %ecx /* zero bss */ + movl $__bss_start, %edi + subl %edi, %ecx + shr $2, %ecx /* _end and __bss_start are aligned */ + xor %eax, %eax + rep + stosl + + testb $X86_BP_FLAGS_LBA64VALID, boot_params+4 + jnz 1f + xorl %ebp, %ebp /* high part of LBA is not valid */ +1: + + movzbl %dl, %edx + push %ebp /* high 32 bits of first sector */ + push %ebx /* first sector of bios partition */ + push %edx /* bios disk */ + call _C_LABEL(boot2) /* C bootstrap code */ + addl $12, %esp + call prot_to_real + .code16 + +boot_fail: + push %ax + movw $1f, %si + call message + pop %si + call message + jmp loopstop +1: .asciz "Boot2 failed: " + +ENTRY(_rtt) + .code32 + call prot_to_real + .code16 +loopstop: + movb $0x86, %ah /* delay for about a second */ + movw $16, %cx + int $0x15 + int $0x18 /* might be a boot fail entry */ +1: sti + hlt + jmp 1b diff --git a/sys/arch/i386/stand/boot/biosboot/Makefile b/sys/arch/i386/stand/boot/biosboot/Makefile new file mode 100644 index 000000000..96780c17b --- /dev/null +++ b/sys/arch/i386/stand/boot/biosboot/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $ + +PROG= boot + +.include <../Makefile.boot> diff --git a/sys/arch/i386/stand/boot/boot2.c b/sys/arch/i386/stand/boot/boot2.c new file mode 100644 index 000000000..6356bcba4 --- /dev/null +++ b/sys/arch/i386/stand/boot/boot2.c @@ -0,0 +1,522 @@ +/* $NetBSD: boot2.c,v 1.57 2011/12/25 06:09:09 tsutsui Exp $ */ + +/*- + * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2003 + * David Laight. All rights reserved + * Copyright (c) 1996, 1997, 1999 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996, 1997 + * Perry E. Metzger. All rights reserved. + * Copyright (c) 1997 + * Jason R. Thorpe. All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Based on stand/biosboot/main.c */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include "devopen.h" + +#ifdef SUPPORT_PS2 +#include +#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] []\n" + "userconf {command}\n" + "rndseed {path_to_rndseed_file}\n" + "help|?\n" + "quit\n"); +} + +void +command_ls(char *arg) +{ + const char *save = default_filename; + + default_filename = "/"; + ls(arg); + default_filename = save; +} + +/* ARGSUSED */ +void +command_quit(char *arg) +{ + + printf("Exiting...\n"); + delay(1000000); + reboot(); + /* Note: we shouldn't get to this point! */ + panic("Could not reboot!"); +} + +void +command_boot(char *arg) +{ + char *filename; + int howto; + + if (parseboot(arg, &filename, &howto)) + bootit(filename, howto, (howto & AB_VERBOSE) != 0); +} + +void +command_dev(char *arg) +{ + static char savedevname[MAXDEVNAME + 1]; + char *fsname, *devname; + const char *file; /* dummy */ + + if (*arg == '\0') { + biosdisk_probe(); + printf("default %s%d%c\n", default_devname, default_unit, + 'a' + default_partition); + return; + } + + if (strchr(arg, ':') == NULL || + parsebootfile(arg, &fsname, &devname, &default_unit, + &default_partition, &file)) { + command_help(NULL); + return; + } + + /* put to own static storage */ + strncpy(savedevname, devname, MAXDEVNAME + 1); + default_devname = savedevname; +} + +static const struct cons_devs { + const char *name; + u_int tag; +} cons_devs[] = { + { "pc", CONSDEV_PC }, + { "com0", CONSDEV_COM0 }, + { "com1", CONSDEV_COM1 }, + { "com2", CONSDEV_COM2 }, + { "com3", CONSDEV_COM3 }, + { "com0kbd", CONSDEV_COM0KBD }, + { "com1kbd", CONSDEV_COM1KBD }, + { "com2kbd", CONSDEV_COM2KBD }, + { "com3kbd", CONSDEV_COM3KBD }, + { "auto", CONSDEV_AUTO }, + { NULL, 0 } +}; + +void +command_consdev(char *arg) +{ + const struct cons_devs *cdp; + + for (cdp = cons_devs; cdp->name; cdp++) { + if (strcmp(arg, cdp->name) == 0) { + initio(cdp->tag); + print_banner(); + return; + } + } + printf("invalid console device.\n"); +} + +void +command_modules(char *arg) +{ + + if (strcmp(arg, "enabled") == 0 || + strcmp(arg, "on") == 0) + boot_modules_enabled = true; + else if (strcmp(arg, "disabled") == 0 || + strcmp(arg, "off") == 0) + boot_modules_enabled = false; + else + printf("invalid flag, must be 'enabled' or 'disabled'.\n"); +} + +void +command_multiboot(char *arg) +{ + char *filename; + + filename = arg; + if (exec_multiboot(filename, gettrailer(arg)) < 0) + printf("multiboot: %s: %s\n", sprint_bootsel(filename), + strerror(errno)); + else + printf("boot returned\n"); +} + diff --git a/sys/arch/i386/stand/boot/conf.c b/sys/arch/i386/stand/boot/conf.c new file mode 100644 index 000000000..fa45ac269 --- /dev/null +++ b/sys/arch/i386/stand/boot/conf.c @@ -0,0 +1,79 @@ +/* $NetBSD: conf.c,v 1.5 2008/04/05 18:21:34 tsutsui Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +#include + +#include +#include +#include +#ifdef SUPPORT_EXT2FS +#include +#endif +#ifdef SUPPORT_MINIXFS3 +#include +#endif +#ifdef SUPPORT_USTARFS +#include +#endif +#ifdef SUPPORT_DOSFS +#include +#endif +#ifdef SUPPORT_CD9660 +#include +#endif + +#include + +struct devsw devsw[] = { + {"disk", biosdisk_strategy, biosdisk_open, biosdisk_close, + biosdisk_ioctl}, +}; +int ndevs = sizeof(devsw) / sizeof(struct devsw); + +struct fs_ops file_system[] = { +#ifdef SUPPORT_CD9660 + FS_OPS(cd9660), +#endif +#ifdef SUPPORT_USTARFS + FS_OPS(ustarfs), +#endif + FS_OPS(ffsv1), FS_OPS(ffsv2), + FS_OPS(lfsv1), FS_OPS(lfsv2), +#ifdef SUPPORT_EXT2FS + FS_OPS(ext2fs), +#endif +#ifdef SUPPORT_MINIXFS3 + FS_OPS(minixfs3), +#endif +#ifdef SUPPORT_DOSFS + FS_OPS(dosfs), +#endif +}; +int nfsys = sizeof(file_system) / sizeof(struct fs_ops); diff --git a/sys/arch/i386/stand/boot/devopen.c b/sys/arch/i386/stand/boot/devopen.c new file mode 100644 index 000000000..7d504d377 --- /dev/null +++ b/sys/arch/i386/stand/boot/devopen.c @@ -0,0 +1,146 @@ +/* $NetBSD: devopen.c,v 1.8 2010/12/24 20:40:42 jakllsch Exp $ */ + +/*- + * Copyright (c) 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bang Jun-Young. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996, 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +#include +#include + +#include +#include +#include "devopen.h" +#ifdef _STANDALONE +#include +#endif +#ifdef SUPPORT_PS2 +#include +#endif + +static int dev2bios(char *, int, int *); + +static int +dev2bios(char *devname, int unit, int *biosdev) +{ + + if (strcmp(devname, "hd") == 0) + *biosdev = 0x80 + unit; + else if (strcmp(devname, "fd") == 0) + *biosdev = 0x00 + unit; + else if (strcmp(devname, "cd") == 0) + *biosdev = boot_biosdev; + else + return ENXIO; + + return 0; +} + +void +bios2dev(int biosdev, daddr_t sector, char **devname, int *unit, int *partition) +{ + + /* set default */ + *unit = biosdev & 0x7f; + + if (biosdev & 0x80) { + /* + * There seems to be no standard way of numbering BIOS + * CD-ROM drives. The following method is a little tricky + * but works nicely. + */ + if (biosdev >= 0x80 + get_harddrives()) { + *devname = "cd"; + *unit = 0; /* override default */ + } else + *devname = "hd"; + } else + *devname = "fd"; + + *partition = biosdisk_findpartition(biosdev, sector); +} + +#ifdef _STANDALONE +struct btinfo_bootpath bibp; +extern bool kernel_loaded; +#endif + +/* + * Open the BIOS disk device + */ +int +devopen(struct open_file *f, const char *fname, char **file) +{ + char *fsname, *devname; + int unit, partition; + int biosdev; + int error; + + if ((error = parsebootfile(fname, &fsname, &devname, + &unit, &partition, (const char **) file)) + || (error = dev2bios(devname, unit, &biosdev))) + return error; + + f->f_dev = &devsw[0]; /* must be biosdisk */ + +#ifdef _STANDALONE + if (!kernel_loaded) { + strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath)); + BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); + } +#endif + + return biosdisk_open(f, biosdev, partition); +} diff --git a/sys/arch/i386/stand/boot/devopen.h b/sys/arch/i386/stand/boot/devopen.h new file mode 100644 index 000000000..2291914d5 --- /dev/null +++ b/sys/arch/i386/stand/boot/devopen.h @@ -0,0 +1,5 @@ +/* $NetBSD: devopen.h,v 1.4 2010/12/24 20:40:42 jakllsch Exp $ */ + +extern int boot_biosdev; + +void bios2dev(int, daddr_t, char **, int *, int *); diff --git a/sys/arch/i386/stand/boot/version b/sys/arch/i386/stand/boot/version new file mode 100644 index 000000000..600e3dc3d --- /dev/null +++ b/sys/arch/i386/stand/boot/version @@ -0,0 +1,49 @@ +$NetBSD: version,v 1.15 2011/02/09 04:37:54 jmcneill Exp $ + +NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this +file is important - make sure the entries are appended on end, last item +is taken as the current. + +2.0: Change over to Matthias Drochner's two-stage boot system. + All code is completely new. +2.1: New welcoming banner. +2.2: Use common menu / parsing functions with other bootloaders. + New framework to pass information to the kernel. +2.3: Switch to new NetBSD MBR partition ID. +2.4: Support BIOS Int13-Extensions. +2.5: Support ustarfs boot. +2.6: Support ELF boot. +2.7: Support on-the-fly switching of console devices. +2.8: Support verbose/quiet boot. +2.9: Recognize PS/2 L40 at runtime and use appropriate gate A20 + initialization (rather than using a compile flag). + Recognize ESDI disks and identify them as ed(4) for COMPAT_OLDBOOT. +2.10: g/c COMPAT_OLDBOOT. +2.11: loadfile() update: ELF symbols no longer need backward seeks. +2.12: loadfile() update to avoid backwards seeks for ELF Program Headers. +2.13: Support boot from 1.44MB floppies in 2.88MB floppy drives. +2.14: Add a quirk for BIOSes which report extended memory size + in slightly nonstandard way in int15, function 0xE801. +2.15: Use int15/0xc7 to get memory information on machines which support + it, like later IBM PS/2 machines. +2.16: Move 16bit %ss to allow >64k for code, data and stack. + Default partition to that passed in by mbr code. + Support limited filename globbing in 'ls' command. + Use .code16 and .code32 directives +3.0: Separate out into bootxx and boot +3.1: Rename to /usr/mdec/boot. + Leave space in bootxx for FAT32 BPB and MBR partition table. + Keep MBR's existing BPB and partition table when installing bootxx. +3.2: Add support for passing boot wedge information to the kernel. +3.3: Add support for cd9660 file system. +5.0: Support for boot menu, modules. +5.1: Change boot messages to replace build date with kernel version. +5.2: Support for multiboot. +5.3: Autoload kernel module for root file system. +5.4: The VESA VBE mode number is now passed to the kernel so it can be + restored on ACPI resume. +5.5: Adjust stack and heap areas to not overlap. +5.6: GUID Partition Table support. +5.7: Recognize 64-bit LBA from bootxx. +5.8: Support for splash images. +5.9: VESA VBE/DDC EDID support. diff --git a/sys/arch/i386/stand/bootxx/Makefile b/sys/arch/i386/stand/bootxx/Makefile new file mode 100644 index 000000000..05a3da261 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.14 2010/12/29 17:44:03 jakllsch Exp $ + +SUBDIR= bootxx_ffsv1 .WAIT bootxx_ffsv2 bootxx_lfsv1 bootxx_lfsv2 +SUBDIR+=bootxx_msdos bootxx_ustarfs + +# Ext2fs doesn't have enough free space (it has only 1KB) +# to store this primary bootloader, but we can put it into +# an independent small 'boot' partition as NetBSD/hp300 does. +SUBDIR+=bootxx_ext2fs +SUBDIR+=bootxx_minixfs3 + +LIBOBJ= ${.OBJDIR} +.MAKEOVERRIDES+= LIBOBJ + +.include +.include + +cleandir distclean: .WAIT cleanlibdir + +cleanlibdir: + -rm -rf lib diff --git a/sys/arch/i386/stand/bootxx/Makefile.bootxx b/sys/arch/i386/stand/bootxx/Makefile.bootxx new file mode 100644 index 000000000..ab8074512 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/Makefile.bootxx @@ -0,0 +1,154 @@ +# $NetBSD: Makefile.bootxx,v 1.42 2011/06/20 06:52:38 mrg Exp $ + +S= ${.CURDIR}/../../../../.. + +AFLAGS.bootxx.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.label.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.pbr.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} + +PIE_CFLAGS= +PIE_LDFLAGS= +PIE_AFLAGS= +NOMAN= +PROG?= bootxx_${FS} +BINDIR= /usr/mdec +BINMODE= 0444 + +PRIMARY_LOAD_ADDRESS=0x1000 +SECONDARY_LOAD_ADDRESS=0x10000 + +# We ought (need?) to fit into track 0 of a 1.2M floppy. +# This restricts us to 15 sectors (including pbr and label) +BOOTXX_SECTORS?=15 +BOOTXX_MAXSIZE?= $$(( ${BOOTXX_SECTORS} * 512 )) + +SRCS= pbr.S label.S bootxx.S boot1.c + +.include + +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 diff --git a/sys/arch/i386/stand/bootxx/boot1.c b/sys/arch/i386/stand/bootxx/boot1.c new file mode 100644 index 000000000..9ecbb479a --- /dev/null +++ b/sys/arch/i386/stand/bootxx/boot1.c @@ -0,0 +1,158 @@ +/* $NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__RCSID("$NetBSD: boot1.c,v 1.20 2011/01/06 01:08:48 jakllsch Exp $"); + +#include +#include +#include + +#include +#include +#include +#include /* For RF_PROTECTED_SECTORS */ + +#define XSTR(x) #x +#define STR(x) XSTR(x) + +static daddr_t bios_sector; + +static struct biosdisk_ll d; + +const char *boot1(uint32_t, uint64_t *); +extern void putstr(const char *); + +extern struct disklabel ptn_disklabel; + +static int +ob(void) +{ + return open("boot", 0); +} + +const char * +boot1(uint32_t biosdev, uint64_t *sector) +{ + struct stat sb; + int fd; + + bios_sector = *sector; + d.dev = biosdev; + + putstr("\r\nNetBSD/x86 " STR(FS) " Primary Bootstrap\r\n"); + + if (set_geometry(&d, NULL)) + return "set_geometry\r\n"; + + /* + * We default to the filesystem at the start of the + * MBR partition + */ + fd = ob(); + if (fd != -1) + goto done; + /* + * Maybe the filesystem is enclosed in a raid set. + * add in size of raidframe header and try again. + * (Maybe this should only be done if the filesystem + * magic number is absent.) + */ + bios_sector += RF_PROTECTED_SECTORS; + fd = ob(); + if (fd != -1) + goto done; + +#ifdef BOOT_FROM_MINIXFS3 + bios_sector -= RF_PROTECTED_SECTORS; + bios_sector += 32; /* XXX put somewhere as constant */ + *sector = bios_sector; + + fd = ob(); + if (fd != -1) + goto done; +#endif + + /* + * Nothing at the start of the MBR partition, fallback on + * partition 'a' from the disklabel in this MBR partition. + */ + if (ptn_disklabel.d_magic != DISKMAGIC || + ptn_disklabel.d_magic2 != DISKMAGIC || + ptn_disklabel.d_partitions[0].p_fstype == FS_UNUSED) + goto done; + bios_sector = ptn_disklabel.d_partitions[0].p_offset; + *sector = bios_sector; + if (ptn_disklabel.d_partitions[0].p_fstype == FS_RAID) + bios_sector += RF_PROTECTED_SECTORS; + + fd = ob(); + +done: + /* if we fail here, so will fstat, so keep going */ + if (fd == -1 || fstat(fd, &sb) == -1) + return "Can't open /boot\r\n"; + + biosdev = (uint32_t)sb.st_size; +#if 0 + if (biosdev > SECONDARY_MAX_LOAD) + return "/boot too large\r\n"; +#endif + + if (read(fd, (void *)SECONDARY_LOAD_ADDRESS, biosdev) != biosdev) + return "/boot load failed\r\n"; + + if (*(uint32_t *)(SECONDARY_LOAD_ADDRESS + 4) != X86_BOOT_MAGIC_2) + return "Invalid /boot file format\r\n"; + + /* We need to jump to the secondary bootstrap in realmode */ + return 0; +} + +int +blkdevstrategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) +{ + if (flag != F_READ) + return EROFS; + + if (size & (BIOSDISK_DEFAULT_SECSIZE - 1)) + return EINVAL; + + if (rsize) + *rsize = size; + + if (size != 0 && readsects(&d, bios_sector + dblk, + size / BIOSDISK_DEFAULT_SECSIZE, + buf, 1) != 0) + return EIO; + + return 0; +} diff --git a/sys/arch/i386/stand/bootxx/bootxx.S b/sys/arch/i386/stand/bootxx/bootxx.S new file mode 100644 index 000000000..ead430c41 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx.S @@ -0,0 +1,136 @@ +/* $NetBSD: bootxx.S,v 1.10 2011/01/06 01:08:48 jakllsch Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +/* + * 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 + . = bootxx + 0x80 /* Space for patching unknown params */ + +1: call gdt_fixup + + calll real_to_prot + .code32 + + push %edi + movl $_end, %ecx /* zero bss */ + movl $__bss_start, %edi + subl %edi, %ecx + shr $2, %ecx /* _end and __bss_start are aligned */ + xor %eax, %eax + rep + stosl + pop %edi + + movzbl %dl, %edx + push %edi /* save args for secondary bootstrap */ + push %esi + movl %esp, %esi /* address of sector number */ + push %edx + push %esi /* args for boot1 */ + push %edx + call _C_LABEL(boot1) /* C code to load /boot */ + add $8, %esp + call prot_to_real + .code16 + + test %ax, %ax + jnz boot_fail + + pop %edx /* bios disk number */ + pop %ebx /* expected partition start sector */ + pop %ecx + movl $boot_params, %esi + orb $X86_BP_FLAGS_LBA64VALID, 4(%esi) + lcall $SECONDARY_LOAD_ADDRESS/16, $0 + +boot_fail: + push %ax /* error string from boot1 */ + movw errno, %ax + aam /* largest errno is < 100 */ + addw $('0' << 8) | '0', %ax /* to ascii */ + rorw $8, %ax + cmpb $'0', %al /* supress leading zero */ + jne 10f + movb $' ', %al +10: movw %ax, 12f + movw $11f, %si + call message /* output boot failed message */ + pop %si + call message /* and text from boot1 */ + jmp loopstop +11: .ascii "Boot failed (errno " +12: .asciz "xx): " + +ENTRY(_rtt) + .code32 + call prot_to_real + .code16 +loopstop: + movb 0x86, %ah /* delay for about a second */ + movw $16, %cx + int $0x15 + int $0x18 /* might be a boot fail entry */ +1: sti /* if not loopstop */ + hlt + jmp 1b + + /* + * Vector the fs calls through here so we can support multiple + * file system types with one copy of the library code and + * multiple copies of this file. + */ + .global xxfs_open, xxfs_close, xxfs_read, xxfs_stat + .code32 +xxfs_open: jmp XXfs_open +xxfs_close: jmp XXfs_close +xxfs_read: jmp XXfs_read +xxfs_stat: jmp XXfs_stat diff --git a/sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile new file mode 100644 index 000000000..6486276ac --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_ext2fs/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2010/09/11 13:06:37 tsutsui Exp $ + +FS=ext2fs + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile new file mode 100644 index 000000000..349cbfcf2 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_ffsv1/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $ + +FS=ffsv1 + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile new file mode 100644 index 000000000..f4d381625 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_ffsv2/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $ + +FS=ffsv2 + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile b/sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile new file mode 100644 index 000000000..b2a8ce3d7 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_lfsv1/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:10 dsl Exp $ + +FS=lfsv1 + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile b/sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile new file mode 100644 index 000000000..55cec87e3 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_lfsv2/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2003/04/16 22:26:11 dsl Exp $ + +FS=lfsv2 + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile b/sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile new file mode 100644 index 000000000..ba1e4e855 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_minixfs3/Makefile @@ -0,0 +1,7 @@ +# $NetBSD$ + +PROG=bootxx_minixfs3 +FS=minixfs3 +CPPFLAGS=-DBOOT_FROM_MINIXFS3 -DTERSE_ERROR + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile b/sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile new file mode 100644 index 000000000..536590b8f --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_msdos/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.3 2005/12/11 12:17:48 christos Exp $ + +PROG= bootxx_msdos +FS= dosfs +CPPFLAGS=-DBOOT_FROM_FAT -DTERSE_ERROR + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile b/sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile new file mode 100644 index 000000000..5fde874e5 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/bootxx_ustarfs/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.3 2009/11/18 21:02:16 dsl Exp $ + +FS=ustarfs + +BOOTXX_SECTORS=16 + +.include <../Makefile.bootxx> diff --git a/sys/arch/i386/stand/bootxx/label.S b/sys/arch/i386/stand/bootxx/label.S new file mode 100644 index 000000000..dc4b98642 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/label.S @@ -0,0 +1,19 @@ +/* $NetBSD: label.S,v 1.3 2005/12/11 12:17:48 christos Exp $ */ + +#include + +/* + * This fills in the space taken by the NetBSD disklabel in the first + * NetBSD partition on the disk. + * However it is possible that we are booting from a subsequent + * NetBSD partition, so must not access the disklabel in this space. + * + * Recent kernels (but not the disklabel program) write the label to + * all NetBSD MBR partitions (including extended ones). + * So we make it available to boot1(). + */ + + .text + .global _C_LABEL(ptn_disklabel) +_C_LABEL(ptn_disklabel): + .fill 512 diff --git a/sys/arch/i386/stand/bootxx/pbr.S b/sys/arch/i386/stand/bootxx/pbr.S new file mode 100644 index 000000000..d93983b29 --- /dev/null +++ b/sys/arch/i386/stand/bootxx/pbr.S @@ -0,0 +1,447 @@ +/* $NetBSD: pbr.S,v 1.20 2011/08/17 00:07:38 jakllsch Exp $ */ + +/*- + * Copyright (c) 2003,2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * i386 partition boot code + * + * This code resides in sector zero of the netbsd partition, or sector + * zero of an unpartitioned disk (eg a floppy). + * Sector 1 is assumed to contain the netbsd disklabel. + * Sectors 2 until the end of the track contain the next phase of bootstrap. + * Which know how to read the interactive 'boot' program from filestore. + * The job of this code is to read in the phase 1 bootstrap. + * + * Makefile supplies: + * PRIMARY_LOAD_ADDRESS: Address we load code to (0x1000). + * BOOTXX_SECTORS: Number of sectors we load (15). + * X86_BOOT_MAGIC_1: A random magic number. + * + * Although this code is executing at 0x7c00, it is linked to address 0x1000. + * All data references MUST be fixed up using R(). + */ + +#include +#include + +#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 +#if 0 +#include +#endif + +/* Control block for int-13 LBA read. */ +_lba_info: + .word 0x10 /* control block length */ + .word BOOTXX_SECTORS /* sector count */ + .word BOOTADDR /* offset in segment */ + .word 0 /* segment */ +_lba_sector: + .quad 0 /* sector # goes here... */ + +/* Drive Serial Number */ + . = _C_LABEL(start) + MBR_DSN_OFFSET + .long 0 + +/* mbr_bootsel_magic (not used here) */ + . = _C_LABEL(start) + MBR_BS_MAGIC_OFFSET + .word 0 + +/* + * Provide empty MBR partition table. + * If this is installed as an MBR, the user can use fdisk(8) to create + * the correct partition table ... + */ + . = _C_LABEL(start) + MBR_PART_OFFSET +_pbr_part0: + .byte 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0 +_pbr_part1: + .byte 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0 +_pbr_part2: + .byte 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0 +_pbr_part3: + .byte 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0 + +/* + * The magic comes last + */ + . = _C_LABEL(start) + MBR_MAGIC_OFFSET +pbr_magic: + .word MBR_MAGIC diff --git a/sys/arch/i386/stand/lib/Makefile b/sys/arch/i386/stand/lib/Makefile new file mode 100644 index 000000000..a94e0288d --- /dev/null +++ b/sys/arch/i386/stand/lib/Makefile @@ -0,0 +1,80 @@ +# $NetBSD: Makefile,v 1.35 2011/06/22 02:49:44 mrg Exp $ + +S?= ${.CURDIR}/../../../.. + +LIB= i386 +NOPIC=# defined +NOPROFILE=# defined + +I386_INCLUDE_DISK?= yes +I386_INCLUDE_DOS?= no +I386_INCLUDE_BUS?= no +I386_INCLUDE_PS2?= yes + +AFLAGS.biosdelay.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosgetrtc.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosgetsystime.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosmca.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosmemps2.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosmem.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosmemx.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosreboot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosvbe.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.biosvideomode.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.bios_disk.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.bios_pci.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.comio.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.conio.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.dos_file.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.dump_eax.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.message.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.message32.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.pvcopy.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.putstr.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.putstr32.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} +AFLAGS.realprot.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} + +CPPFLAGS= -I$S/lib/libsa ${I386CPPFLAGS} ${I386MISCCPPFLAGS} +#CPPFLAGS+= -DDISK_DEBUG +#CPPFLAGS+= -DNO_DISKLABEL +#CPPFLAGS+= -DNO_GPT +#CPPFLAGS+= -DSAVE_MEMORY + +SRCS= pcio.c conio.S comio.S comio_direct.c biosvideomode.S +SRCS+= getsecs.c biosgetrtc.S biosdelay.S biosreboot.S gatea20.c +SRCS+= biosmem.S getextmemx.c biosmemx.S printmemlist.c +SRCS+= pread.c menuutils.c parseutils.c +SRCS+= bootinfo.c bootinfo_biosgeom.c bootinfo_memmap.c +SRCS+= startprog.S multiboot.S +SRCS+= biosgetsystime.S cpufunc.S bootmenu.c +SRCS+= realprot.S message.S message32.S dump_eax.S pvcopy.S putstr.S putstr32.S +SRCS+= rasops.c vbe.c biosvbe.S +.if (${I386_INCLUDE_DISK} == "yes") +SRCS+= biosdisk.c biosdisk_ll.c bios_disk.S +.endif +.if (${I386_INCLUDE_DOS} == "yes") +SRCS+= dosfile.c dos_file.S +.endif +.if (${I386_INCLUDE_DISK} == "yes") || (${I386_INCLUDE_DOS} == "yes") +SRCS+= diskbuf.c +.endif +.if (${I386_INCLUDE_BUS} == "yes") +SRCS+= biospci.c bios_pci.S isapnp.c isadma.c +.endif +.if (${I386_INCLUDE_PS2} == "yes") +SRCS+= biosmca.S biosmemps2.S +.endif + +.include +.undef DESTDIR +.include + +lib${LIB}.o:: ${OBJS} + @echo building standard ${LIB} library + @rm -f lib${LIB}.o + @${LD} -r -o lib${LIB}.o `lorder ${OBJS} | tsort` + +# XXX +.if ${HAVE_GCC} == 45 +COPTS.biosdisk.c+= -fno-strict-aliasing +.endif diff --git a/sys/arch/i386/stand/lib/Makefile.inc b/sys/arch/i386/stand/lib/Makefile.inc new file mode 100644 index 000000000..754a38525 --- /dev/null +++ b/sys/arch/i386/stand/lib/Makefile.inc @@ -0,0 +1,55 @@ +# $NetBSD: Makefile.inc,v 1.14 2011/05/26 12:56:30 joerg Exp $ +# +# Configuration variables (default values are below): +# +# S must be set to the top of the 'sys' tree. +# I386DST may be set to the location of the directory where library +# objects are to be built. Defaults to ${.OBJDIR}/lib/i386. +# I386MISCCPPFLAGS +# Miscellaneous cpp flags to be passed to the library's Makefile +# when building. +# I386MISCMAKEFLAGS +# Miscellaneous flags to be passed to the library's Makefile when +# building. See library's Makefile for more details about +# supported flags and their default values. + +# Default values: +I386DST?= ${.OBJDIR}/lib/i386 + +#I386DIR= $S/arch/i386/stand/lib +I386LIB= ${I386DST}/libi386.a + +CWARNFLAGS.clang+= -Wno-tautological-compare + +I386MAKE= \ + cd ${I386DIR} && MAKEOBJDIRPREFIX= && unset MAKEOBJDIRPREFIX && \ + MAKEOBJDIR=${I386DST} ${MAKE} \ + CC=${CC:Q} CFLAGS=${CFLAGS:Q} \ + AS=${AS:Q} AFLAGS=${AFLAGS:Q} \ + LD=${LD:Q} STRIP=${STRIP:Q} \ + MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \ + I386CPPFLAGS=${CPPFLAGS:S@^-I.@-I../../.@g:Q} \ + I386MISCCPPFLAGS=${I386MISCCPPFLAGS:Q} \ + ${I386MISCMAKEFLAGS} + +${I386LIB}: .NOTMAIN __always_make_i386lib + @echo making sure the i386 library is up to date... + @${I386MAKE} libi386.a + +clean: .NOTMAIN cleani386lib +cleani386lib: .NOTMAIN + @echo cleaning the i386 library objects + @if [ -d "${I386DST}" ]; then ${I386MAKE} clean; fi + +cleandir distclean: .NOTMAIN cleandiri386lib +cleandiri386lib: .NOTMAIN + @echo cleandiring the i386 library objects + @if [ -d "${I386DST}" ]; then ${I386MAKE} cleandir; fi + +dependall depend: .NOTMAIN dependi386lib +dependi386lib: .NOTMAIN __always_make_i386lib + @echo depending the i386 library objects + @${I386MAKE} depend + +__always_make_i386lib: .NOTMAIN + @mkdir -p ${I386DST} diff --git a/sys/arch/i386/stand/lib/bios_disk.S b/sys/arch/i386/stand/lib/bios_disk.S new file mode 100644 index 000000000..578966e11 --- /dev/null +++ b/sys/arch/i386/stand/lib/bios_disk.S @@ -0,0 +1,297 @@ +/* $NetBSD: bios_disk.S,v 1.21 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* extracted from netbsd:sys/arch/i386/boot/bios.S */ + +#include + +/* + * BIOS call "INT 0x13 Function 0x0" to reset the disk subsystem + * Call with %ah = 0x0 + * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) + * Return: + * %al = 0x0 on success; err code on failure + */ +ENTRY(biosdisk_reset) + pusha + + movb %al, %dl # device + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x0, %ah # subfunction + int $0x13 + setc %bl + movb %ah, %bh # save error code + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movzwl %bx, %eax # return value in %eax + movl %eax, 28(%esp) + + popa + ret + +/* + * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory + * Call with %ah = 0x2 + * %al = number of sectors + * %ch = cylinder + * %cl = sector + * %dh = head + * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) + * %es:%bx = segment:offset of buffer + * Return: + * %al = 0x0 on success; err code on failure + * + * biosdisk_read(dev, cyl, head, sect, count, buff_addr); + * + * Note: On failure, you must reset the disk with biosdisk_reset() before + * sending another command. + */ +ENTRY(biosdisk_read) + pusha + + movb 44(%esp), %dh + movw 40(%esp), %cx + xchgb %ch, %cl # cylinder; the highest 2 bits of cyl is in %cl + rorb $2, %cl + movb 48(%esp), %al + orb %al, %cl + incb %cl # sector; sec starts from 1, not 0 + movb 36(%esp), %dl # device + movl 56(%esp), %ebx # buffer address (may be >64k) + movb 52(%esp), %al # number of sectors + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %bx + shrl $4, %ebx # max segment + mov %ds, %si + add %si, %bx + mov %bx, %es # %es:%bx now valid buffer address + pop %bx + and $0xf, %bx # and min offset - to avoid overrun + + movb $0x2, %ah # subfunction + int $0x13 + setc %al # error code is in %ah + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %eax, 28(%esp) + + popa + ret + +/* + * biosdisk_getinfo(int dev): return a word that represents the + * max number of sectors, heads and cylinders for this device + */ +ENTRY(biosdisk_getinfo) + push %es + pusha + + movb %al, %dl # diskinfo(drive #) + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %dx # save drive # + movb $0x08, %ah # ask for disk info + int $0x13 + pop %bx # restore drive # + jnc ok + + testb $0x80, %bl # is it a hard disk? + jnz ok + + /* + * Urk. Call failed. It is not supported for floppies by old BIOS's. + * Guess it's a 15-sector floppy. Initialize all the registers for + * documentation, although we only need head and sector counts. + */ + xorw %ax, %ax # set status to success +# movb %ah, %bh # %bh = 0 +# movb $2, %bl # %bl bits 0-3 = drive type, 2 = 1.2M + movb $79, %ch # max track + movb $15, %cl # max sector + movb $1, %dh # max head +# movb $1, %dl # # floppy drives installed + # es:di = parameter table + # carry = 0 + +ok: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + /* form a longword representing all this gunk */ + shrl $8, %eax # clear unnecessary bits + shll $24, %eax + shll $16, %ecx # do the same for %ecx + shrl $8, %ecx + movb %dh, %cl # max head + orl %ecx, %eax # return value in %eax + movl %eax, 28(%esp) + + popa + pop %es + ret + +/* + * int biosdisk_int13ext(int dev): + * check for availibility of int13 extensions. + */ +ENTRY(biosdisk_int13ext) + pusha + + movb %al, %dl # drive # + movw $0x55aa, %bx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x41, %ah # ask for disk info + int $0x13 + setnc %dl + + calll _C_LABEL(real_to_prot) # switch back + .code32 + + movzbl %dl, %eax # return value in %eax + + cmpw $0xaa55, %bx + sete %dl + andb %dl, %al + + andb %cl, %al + movl %eax, 28(%esp) + + popa + ret + +/* + * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory + * Call with %ah = 0x42 + * %ds:%si = parameter block (data buffer address + * must be a real mode physical address). + * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) + * Return: + * %al = 0x0 on success; err code on failure + */ +ENTRY(biosdisk_extread) + pusha + + movl %edx, %esi # parameter block + movb %al, %dl # device + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %ds + movl %esi, %eax + shrl $4, %eax + movw %ds, %bx + addw %bx, %ax + movw %ax, %ds + andw $0xf, %si + + movb $0x42, %ah # subfunction + int $0x13 + setc %bl + movb %ah, %bh # save error code + pop %ds + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movzwl %bx, %eax # return value in %eax + movl %eax, 28(%esp) + + popa + ret + +ENTRY(biosdisk_getextinfo) + pusha + + movl %edx, %esi # parameter block + movb %al, %dl # device + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %ds + movl %esi, %eax + shrl $4, %eax + andw $0xf, %si + movw %ds, %bx + addw %bx, %ax + movw %ax, %ds + + movb $0x48, %ah # subfunction + int $0x13 + setc %bl + pop %ds + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movzbl %bl, %eax # return value in %eax + movl %eax, 28(%esp) + + popa + ret diff --git a/sys/arch/i386/stand/lib/bios_pci.S b/sys/arch/i386/stand/lib/bios_pci.S new file mode 100644 index 000000000..a62d20c63 --- /dev/null +++ b/sys/arch/i386/stand/lib/bios_pci.S @@ -0,0 +1,214 @@ +/* $NetBSD: bios_pci.S,v 1.6 2005/12/11 12:17:48 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* minimal calls to PCI BIOS */ + +#include + +#define addr32 .byte 0x67 +#define data32 .byte 0x66 + +#define PCI_FUNCTION_ID 0xb1 +#define PCI_BIOS_PRESENT 0x01 +#define FIND_PCI_DEVICE 0x02 +#define READ_CONFIG_DWORD 0x0a +#define WRITE_CONFIG_DWORD 0x0d + +/* int pcibios_present(int *signature) + return: AX from BIOS call, -1 on error + var param: EDX from BIOS call, must be signature "PCI " +*/ +ENTRY(pcibios_present) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $PCI_FUNCTION_ID, %ah + movb $PCI_BIOS_PRESENT, %al + int $0x1a + + jnc ok1 + movl $-1, %ebx + jmp err1 + +ok1: + xorl %ebx, %ebx + mov %ax, %bx +err1: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl 8(%ebp), %eax + movl %edx, (%eax) + + movl %ebx, %eax # return value in %eax + + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* int pcibios_finddev(int vendor, int device, int index, int *busdevfcn) + return: AH from BIOS call, -1 on error + var param: BX from BIOS call, contains bus/device/function +*/ +ENTRY(pcibios_finddev) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + + movl 8(%ebp), %edx + movl 12(%ebp), %ecx + movl 16(%ebp), %esi + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $PCI_FUNCTION_ID, %ah + movb $FIND_PCI_DEVICE, %al + int $0x1a + + jnc ok2 + movl $-1, %edx + jmp err2 + +ok2: + movl $0,%edx + movb %ah, %dl +err2: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl 20(%ebp), %eax + mov %bx, (%eax) + + movl %edx, %eax # return value in %eax + + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* int pcibios_cfgread(int busdevfcn, int offset, int *value) + return: AH from BIOS call, -1 on error + var param: ECX from BIOS call, contains value read +*/ +ENTRY(pcibios_cfgread) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + + movl 8(%ebp), %ebx + movl 12(%ebp), %edi + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $PCI_FUNCTION_ID, %ah + movb $READ_CONFIG_DWORD, %al + int $0x1a + + jnc ok3 + movl $-1, %edx + jmp err3 + +ok3: + movl $0,%edx + movb %ah, %dl +err3: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl 16(%ebp), %eax + movl %ecx, (%eax) + + movl %edx, %eax # return value in %eax + + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* int pcibios_cfgwrite(int busdevfcn, int offset, int value) + return: AH from BIOS call, -1 on error + var param: ECX from BIOS call, contains value read +*/ +ENTRY(pcibios_cfgwrite) + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + + movl 8(%ebp), %ebx + movl 12(%ebp), %edi + movl 16(%ebp), %ecx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $PCI_FUNCTION_ID, %ah + movb $WRITE_CONFIG_DWORD, %al + int $0x1a + + jnc ok4 + movl $-1, %edx + jmp err4 + +ok4: + movl $0,%edx + movb %ah, %dl +err4: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %edx, %eax # return value in %eax + + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/biosdelay.S b/sys/arch/i386/stand/lib/biosdelay.S new file mode 100644 index 000000000..e3925a20d --- /dev/null +++ b/sys/arch/i386/stand/lib/biosdelay.S @@ -0,0 +1,78 @@ +/* $NetBSD: biosdelay.S,v 1.4 2005/12/11 12:17:48 christos Exp $ */ + +/* + * Copyright (c) 1996, 1997 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + + .text + +/* + * BIOS call "INT 15H Function 86H" to sleep for a set number of microseconds + * Call with %ah = 0x86 + * %cx = time interval (high) + * %dx = time interval (low) + * Return: + * If error + * CF = set + * else + * CF = clear + */ +ENTRY(delay) + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + movw 20(%esp), %dx + movw 22(%esp), %cx + + call _C_LABEL(prot_to_real) + .code16 + + movb $0x86, %ah + int $0x15 + setnc %ah + + movb %ah, %bl # real_to_prot uses %eax + + calll _C_LABEL(real_to_prot) + .code32 + + xorl %eax, %eax + movb %bl, %al + + popl %edi + popl %esi + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/biosdisk.c b/sys/arch/i386/stand/lib/biosdisk.c new file mode 100644 index 000000000..13701c722 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosdisk.c @@ -0,0 +1,808 @@ +/* $NetBSD: biosdisk.c,v 1.39 2011/09/21 08:57:12 gsutre Exp $ */ + +/* + * Copyright (c) 1996, 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * raw BIOS disk device for libsa. + * needs lowlevel parts from bios_disk.S and biosdisk_ll.c + * partly from netbsd:sys/arch/i386/boot/disk.c + * no bad144 handling! + * + * A lot of this must match sys/kern/subr_disk_mbr.c + */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) +#define FSTYPENAMES +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "libi386.h" +#include "biosdisk_ll.h" +#include "biosdisk.h" +#ifdef _STANDALONE +#include "bootinfo.h" +#endif + +#define BUFSIZE 2048 /* must be large enough for a CD sector */ + +#define BIOSDISKNPART 26 + +struct biosdisk { + struct biosdisk_ll ll; + daddr_t boff; + char buf[BUFSIZE]; +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) + struct { + daddr_t offset; + daddr_t size; + int fstype; + } part[BIOSDISKNPART]; +#endif +}; + +#ifndef NO_GPT +const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; +const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; +const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; +const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; +#endif /* NO_GPT */ + +#ifdef _STANDALONE +static struct btinfo_bootdisk bi_disk; +static struct btinfo_bootwedge bi_wedge; +#endif + +#define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */ + +int +biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, + void *buf, size_t *rsize) +{ + struct biosdisk *d; + int blks, frag; + + if (flag != F_READ) + return EROFS; + + d = (struct biosdisk *) devdata; + + if (d->ll.type == BIOSDISK_TYPE_CD) + dblk = dblk * DEV_BSIZE / ISO_DEFAULT_BLOCK_SIZE; + + dblk += d->boff; + + blks = size / d->ll.secsize; + if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { + if (rsize) + *rsize = 0; + return EIO; + } + + /* needed for CD */ + frag = size % d->ll.secsize; + if (frag) { + if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { + if (rsize) + *rsize = blks * d->ll.secsize; + return EIO; + } + memcpy(buf + blks * d->ll.secsize, d->buf, frag); + } + + if (rsize) + *rsize = size; + return 0; +} + +static struct biosdisk * +alloc_biosdisk(int biosdev) +{ + struct biosdisk *d; + + d = alloc(sizeof(*d)); + if (d == NULL) + return NULL; + memset(d, 0, sizeof(*d)); + + d->ll.dev = biosdev; + if (set_geometry(&d->ll, NULL)) { +#ifdef DISK_DEBUG + printf("no geometry information\n"); +#endif + dealloc(d, sizeof(*d)); + return NULL; + } + return d; +} + +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) +static void +md5(void *hash, const void *data, size_t len) +{ + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, data, len); + MD5Final(hash, &ctx); + + return; +} +#endif + +#ifndef NO_GPT +static bool +guid_is_nil(const struct uuid *u) +{ + static const struct uuid nil = { .time_low = 0 }; + return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false); +} + +static bool +guid_is_equal(const struct uuid *a, const struct uuid *b) +{ + return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); +} + +static int +check_gpt(struct biosdisk *d, daddr_t sector) +{ + struct gpt_hdr gpth; + const struct gpt_ent *ep; + const struct uuid *u; + daddr_t entblk; + size_t size; + uint32_t crc; + int sectors; + int entries; + int entry; + int i, j; + + /* read in gpt_hdr sector */ + if (readsects(&d->ll, sector, 1, d->buf, 1)) { +#ifdef DISK_DEBUG + printf("Error reading GPT header at %"PRId64"\n", sector); +#endif + return EIO; + } + + gpth = *(const struct gpt_hdr *)d->buf; + + if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig))) + return -1; + + crc = gpth.hdr_crc_self; + gpth.hdr_crc_self = 0; + gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE); + if (gpth.hdr_crc_self != crc) { + return -1; + } + + if (gpth.hdr_lba_self != sector) + return -1; + +#ifdef _STANDALONE + bi_wedge.matchblk = sector; + bi_wedge.matchnblks = 1; + + md5(bi_wedge.matchhash, d->buf, d->ll.secsize); +#endif + + sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ + entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ + entblk = gpth.hdr_lba_table; + crc = crc32(0, NULL, 0); + + j = 0; + ep = (const struct gpt_ent *)d->buf; + + for (entry = 0; entry < gpth.hdr_entries; entry += entries) { + size = MIN(sizeof(d->buf), + (gpth.hdr_entries - entry) * gpth.hdr_entsz); + entries = size / gpth.hdr_entsz; + sectors = roundup(size, d->ll.secsize) / d->ll.secsize; + if (readsects(&d->ll, entblk, sectors, d->buf, 1)) + return -1; + entblk += sectors; + crc = crc32(crc, (const void *)d->buf, size); + + for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) { + u = (const struct uuid *)ep[i].ent_type; + if (!guid_is_nil(u)) { + d->part[j].offset = ep[i].ent_lba_start; + d->part[j].size = ep[i].ent_lba_end - + ep[i].ent_lba_start + 1; + if (guid_is_equal(u, &GET_nbsd_ffs)) + d->part[j].fstype = FS_BSDFFS; + else if (guid_is_equal(u, &GET_nbsd_lfs)) + d->part[j].fstype = FS_BSDLFS; + else if (guid_is_equal(u, &GET_nbsd_raid)) + d->part[j].fstype = FS_RAID; + else if (guid_is_equal(u, &GET_nbsd_swap)) + d->part[j].fstype = FS_SWAP; + else + d->part[j].fstype = FS_OTHER; + } + } + + } + + if (crc != gpth.hdr_crc_table) { +#ifdef DISK_DEBUG + printf("GPT table CRC invalid\n"); +#endif + return -1; + } + + return 0; +} + +static int +read_gpt(struct biosdisk *d) +{ + struct biosdisk_extinfo ed; + daddr_t gptsector[2]; + int i, error; + + if (d->ll.type != BIOSDISK_TYPE_HD) + /* No GPT on floppy and CD */ + return -1; + + gptsector[0] = GPT_HDR_BLKNO; + if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) { + gptsector[1] = ed.totsec - 1; + d->ll.secsize = ed.sbytes; + } else { +#ifdef DISK_DEBUG + printf("Unable to determine extended disk geometry - " + "using CHS\n"); +#endif + /* at least try some other reasonable values then */ + gptsector[1] = d->ll.chs_sectors - 1; + } + + /* + * Use any valid GPT available, do not require both GPTs to be valid + */ + for (i = 0; i < __arraycount(gptsector); i++) { + error = check_gpt(d, gptsector[i]); + if (error == 0) + break; + } + + if (i >= __arraycount(gptsector)) { + memset(d->part, 0, sizeof(d->part)); + return -1; + } + +#ifdef DISK_DEBUG + printf("using %s GPT\n", (i == 0) ? "primary" : "secondary"); +#endif + return 0; +} +#endif /* !NO_GPT */ + +#ifndef NO_DISKLABEL +static void +ingest_label(struct biosdisk *d, struct disklabel *lp) +{ + int part; + + memset(d->part, 0, sizeof(d->part)); + + for (part = 0; part < lp->d_npartitions; part++) { + if (lp->d_partitions[part].p_size == 0) + continue; + if (lp->d_partitions[part].p_fstype == FS_UNUSED) + continue; + d->part[part].fstype = lp->d_partitions[part].p_fstype; + d->part[part].offset = lp->d_partitions[part].p_offset; + d->part[part].size = lp->d_partitions[part].p_size; + } +} + +static int +check_label(struct biosdisk *d, daddr_t sector) +{ + struct disklabel *lp; + + /* find partition in NetBSD disklabel */ + if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { +#ifdef DISK_DEBUG + printf("Error reading disklabel\n"); +#endif + return EIO; + } + lp = (struct disklabel *) (d->buf + LABELOFFSET); + if (lp->d_magic != DISKMAGIC || dkcksum(lp)) { +#ifdef DISK_DEBUG + printf("warning: no disklabel in sector %"PRId64"\n", sector); +#endif + return -1; + } + + ingest_label(d, lp); + +#ifdef _STANDALONE + bi_disk.labelsector = sector + LABELSECTOR; + bi_disk.label.type = lp->d_type; + memcpy(bi_disk.label.packname, lp->d_packname, 16); + bi_disk.label.checksum = lp->d_checksum; + + bi_wedge.matchblk = sector + LABELSECTOR; + bi_wedge.matchnblks = 1; + + md5(bi_wedge.matchhash, d->buf, d->ll.secsize); +#endif + + return 0; +} + +static int +read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl, + int this_ext, daddr_t sector) +{ + struct mbr_partition mbr[MBR_PART_COUNT]; + int i; + int typ; + struct partition *p; + + if (readsects(&d->ll, sector, 1, d->buf, 0)) { +#ifdef DISK_DEBUG + printf("Error reading MFS sector %d\n", sector); +#endif + return EIO; + } + if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) { + return -1; + } + memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, sizeof(mbr)); + for (i = 0; i < MBR_PART_COUNT; i++) { + typ = mbr[i].mbrp_type; + if (typ == 0) + continue; + sector = this_ext + mbr[i].mbrp_start; + if (dflt_lbl->d_npartitions >= MAXPARTITIONS) + continue; + p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++]; + p->p_offset = sector; + p->p_size = mbr[i].mbrp_size; + p->p_fstype = xlat_mbr_fstype(typ); + } + return 0; +} + +static int +read_label(struct biosdisk *d) +{ + struct disklabel dflt_lbl; + struct mbr_partition mbr[MBR_PART_COUNT]; + struct partition *p; + int sector, i; + int error; + int typ; + int ext_base, this_ext, next_ext; +#ifdef COMPAT_386BSD_MBRPART + int sector_386bsd = -1; +#endif + + memset(&dflt_lbl, 0, sizeof(dflt_lbl)); + dflt_lbl.d_npartitions = 8; + + d->boff = 0; + + if (d->ll.type != BIOSDISK_TYPE_HD) + /* No label on floppy and CD */ + return -1; + + /* + * find NetBSD Partition in DOS partition table + * XXX check magic??? + */ + ext_base = 0; + next_ext = 0; + for (;;) { + this_ext = ext_base + next_ext; + next_ext = 0; + if (readsects(&d->ll, this_ext, 1, d->buf, 0)) { +#ifdef DISK_DEBUG + printf("error reading MBR sector %d\n", this_ext); +#endif + return EIO; + } + memcpy(&mbr, ((struct mbr_sector *)d->buf)->mbr_parts, + sizeof(mbr)); + /* Look for NetBSD partition ID */ + for (i = 0; i < MBR_PART_COUNT; i++) { + typ = mbr[i].mbrp_type; + if (typ == 0) + continue; + sector = this_ext + mbr[i].mbrp_start; +#ifdef DISK_DEBUG + printf("ptn type %d in sector %d\n", typ, sector); +#endif + if (typ == MBR_PTYPE_MINIX_14B) { + if (!read_minix_subp(d, &dflt_lbl, + this_ext, sector)) { + /* Don't add "container" partition */ + continue; + } + } + if (typ == MBR_PTYPE_NETBSD) { + error = check_label(d, sector); + if (error >= 0) + return error; + } + if (MBR_IS_EXTENDED(typ)) { + next_ext = mbr[i].mbrp_start; + continue; + } +#ifdef COMPAT_386BSD_MBRPART + if (this_ext == 0 && typ == MBR_PTYPE_386BSD) + sector_386bsd = sector; +#endif + if (this_ext != 0) { + if (dflt_lbl.d_npartitions >= MAXPARTITIONS) + continue; + p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++]; + } else + p = &dflt_lbl.d_partitions[i]; + p->p_offset = sector; + p->p_size = mbr[i].mbrp_size; + p->p_fstype = xlat_mbr_fstype(typ); + } + if (next_ext == 0) + break; + if (ext_base == 0) { + ext_base = next_ext; + next_ext = 0; + } + } + + sector = 0; +#ifdef COMPAT_386BSD_MBRPART + if (sector_386bsd != -1) { + printf("old BSD partition ID!\n"); + sector = sector_386bsd; + } +#endif + + /* + * One of two things: + * 1. no MBR + * 2. no NetBSD partition in MBR + * + * We simply default to "start of disk" in this case and + * press on. + */ + error = check_label(d, sector); + if (error >= 0) + return error; + + /* + * Nothing at start of disk, return info from mbr partitions. + */ + /* XXX fill it to make checksum match kernel one */ + dflt_lbl.d_checksum = dkcksum(&dflt_lbl); + ingest_label(d, &dflt_lbl); + return 0; +} +#endif /* NO_DISKLABEL */ + +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) +static int +read_partitions(struct biosdisk *d) +{ + int error; + + error = -1; + +#ifndef NO_GPT + error = read_gpt(d); + if (error == 0) + return 0; + +#endif +#ifndef NO_DISKLABEL + error = read_label(d); + +#endif + return error; +} +#endif + +void +biosdisk_probe(void) +{ + struct biosdisk d; + struct biosdisk_extinfo ed; + uint64_t size; + int first; + int i; +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) + int part; +#endif + + for (i = 0; i < MAX_BIOSDISKS + 2; i++) { + first = 1; + memset(&d, 0, sizeof(d)); + memset(&ed, 0, sizeof(ed)); + if (i >= MAX_BIOSDISKS) + d.ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ + else + d.ll.dev = 0x80 + i; /* hd/cd */ + if (set_geometry(&d.ll, &ed)) + continue; + printf("disk "); + switch (d.ll.type) { + case BIOSDISK_TYPE_CD: + printf("cd0\n cd0a\n"); + break; + case BIOSDISK_TYPE_FD: + printf("fd%d\n", d.ll.dev & 0x7f); + printf(" fd%da\n", d.ll.dev & 0x7f); + break; + case BIOSDISK_TYPE_HD: + printf("hd%d", d.ll.dev & 0x7f); + if (d.ll.flags & BIOSDISK_INT13EXT) { + printf(" size "); + size = ed.totsec * ed.sbytes; + if (size >= (10ULL * 1024 * 1024 * 1024)) + printf("%"PRIu64" GB", + size / (1024 * 1024 * 1024)); + else + printf("%"PRIu64" MB", + size / (1024 * 1024)); + } + printf("\n"); + break; + } +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) + if (d.ll.type != BIOSDISK_TYPE_HD) + continue; + + if (read_partitions(&d) != 0) + continue; + + for (part = 0; part < BIOSDISKNPART; part++) { + if (d.part[part].size == 0) + continue; + if (d.part[part].fstype == FS_UNUSED) + continue; + if (first) { + printf(" "); + first = 0; + } + printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a'); + if (d.part[part].fstype < FSMAXTYPES) + printf("%s", + fstypenames[d.part[part].fstype]); + else + printf("%d", d.part[part].fstype); + printf(")"); + } +#endif + if (first == 0) + printf("\n"); + } +} + +/* Determine likely partition for possible sector number of dos + * partition. + */ + +int +biosdisk_findpartition(int biosdev, daddr_t sector) +{ +#if defined(NO_DISKLABEL) && defined(NO_GPT) + return 0; +#else + struct biosdisk *d; + int partition = 0; +#ifdef DISK_DEBUG + printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector); +#endif + + /* Look for netbsd partition that is the dos boot one */ + d = alloc_biosdisk(biosdev); + if (d == NULL) + return 0; + + if (read_partitions(d) == 0) { + for (partition = (BIOSDISKNPART-1); --partition;) { + if (d->part[partition].fstype == FS_UNUSED) + continue; + if (d->part[partition].offset == sector) + break; + } + } + + dealloc(d, sizeof(*d)); + return partition; +#endif /* NO_DISKLABEL && NO_GPT */ +} + +#ifdef _STANDALONE +static void +add_biosdisk_bootinfo(void) +{ + static bool done; + + if (bootinfo == NULL) { + done = false; + return; + } + + if (done) + return; + + BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); + BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge)); + + done = true; + + return; +} + +#endif + +int +biosdisk_open(struct open_file *f, ...) +/* struct open_file *f, int biosdev, int partition */ +{ + va_list ap; + struct biosdisk *d; + int biosdev; + int partition; + int error = 0; + + va_start(ap, f); + biosdev = va_arg(ap, int); + d = alloc_biosdisk(biosdev); + if (d == NULL) { + error = ENXIO; + goto out; + } + + partition = va_arg(ap, int); +#ifdef _STANDALONE + bi_disk.biosdev = d->ll.dev; + bi_disk.partition = partition; + bi_disk.labelsector = -1; + + bi_wedge.biosdev = d->ll.dev; + bi_wedge.matchblk = -1; +#endif + +#if !defined(NO_DISKLABEL) || !defined(NO_GPT) + error = read_partitions(d); + if (error == -1) { + error = 0; + goto nolabel; + } + if (error) + goto out; + + if (partition >= BIOSDISKNPART || + d->part[partition].fstype == FS_UNUSED) { +#ifdef DISK_DEBUG + printf("illegal partition\n"); +#endif + error = EPART; + goto out; + } + + d->boff = d->part[partition].offset; + + if (d->part[partition].fstype == FS_RAID) + d->boff += RF_PROTECTED_SECTORS; + +#ifdef _STANDALONE + bi_wedge.startblk = d->part[partition].offset; + bi_wedge.nblks = d->part[partition].size; +#endif + +nolabel: +#endif +#ifdef DISK_DEBUG + printf("partition @%"PRId64"\n", d->boff); +#endif + +#ifdef _STANDALONE + add_biosdisk_bootinfo(); +#endif + + f->f_devdata = d; +out: + va_end(ap); + if (error) + dealloc(d, sizeof(*d)); + return error; +} + +#ifndef LIBSA_NO_FS_CLOSE +int +biosdisk_close(struct open_file *f) +{ + struct biosdisk *d = f->f_devdata; + + /* let the floppy drive go off */ + if (d->ll.type == BIOSDISK_TYPE_FD) + wait_sec(3); /* 2s is enough on all PCs I found */ + + dealloc(d, sizeof(*d)); + f->f_devdata = NULL; + return 0; +} +#endif + +int +biosdisk_ioctl(struct open_file *f, u_long cmd, void *arg) +{ + return EIO; +} diff --git a/sys/arch/i386/stand/lib/biosdisk.h b/sys/arch/i386/stand/lib/biosdisk.h new file mode 100644 index 000000000..216a0cf7b --- /dev/null +++ b/sys/arch/i386/stand/lib/biosdisk.h @@ -0,0 +1,32 @@ +/* $NetBSD: biosdisk.h,v 1.8 2010/12/24 20:36:51 jakllsch Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +int biosdisk_strategy(void *, int, daddr_t, size_t, void *, size_t *); +int biosdisk_open(struct open_file *, ...); +int biosdisk_close(struct open_file *); +int biosdisk_ioctl(struct open_file *, u_long, void *); +int biosdisk_findpartition(int, daddr_t); diff --git a/sys/arch/i386/stand/lib/biosdisk_ll.c b/sys/arch/i386/stand/lib/biosdisk_ll.c new file mode 100644 index 000000000..2eafbc9ac --- /dev/null +++ b/sys/arch/i386/stand/lib/biosdisk_ll.c @@ -0,0 +1,319 @@ +/* $NetBSD: biosdisk_ll.c,v 1.31 2011/02/21 02:58:02 jakllsch Exp $ */ + +/*- + * Copyright (c) 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bang Jun-Young. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * shared by bootsector startup (bootsectmain) and biosdisk.c + * needs lowlevel parts from bios_disk.S + */ + +#include +#include + +#include "biosdisk_ll.h" +#include "diskbuf.h" +#include "libi386.h" + +static int do_read(struct biosdisk_ll *, daddr_t, int, char *); + +/* + * we get from get_diskinfo(): + * %ah %ch %cl %dh (registers after int13/8), ie + * xxxxxxxx cccccccc CCssssss hhhhhhhh + */ +#define STATUS(di) ((di)>>24) +#define SPT(di) (((di)>>8)&0x3f) +#define HEADS(di) (((di)&0xff)+1) +#define CYL(di) (((((di)>>16)&0xff)|(((di)>>6)&0x300))+1) + +#ifndef BIOSDISK_RETRIES +#define BIOSDISK_RETRIES 5 +#endif + +int +set_geometry(struct biosdisk_ll *d, struct biosdisk_extinfo *ed) +{ + int diskinfo; + + diskinfo = biosdisk_getinfo(d->dev); + d->sec = SPT(diskinfo); + d->head = HEADS(diskinfo); + d->cyl = CYL(diskinfo); + d->chs_sectors = d->sec * d->head * d->cyl; + + if (d->dev >= 0x80 + get_harddrives()) { + d->secsize = 2048; + d->type = BIOSDISK_TYPE_CD; + } else { + d->secsize = 512; + if (d->dev & 0x80) + d->type = BIOSDISK_TYPE_HD; + else + d->type = BIOSDISK_TYPE_FD; + } + + /* + * Some broken BIOSes such as one found on Soltek SL-75DRV2 report + * that they don't support int13 extension for CD-ROM drives while + * they actually do. As a workaround, if the boot device is a CD we + * assume that the extension is available. Note that only very old + * BIOSes don't support the extended mode, and they don't work with + * ATAPI CD-ROM drives, either. So there's no problem. + */ + d->flags = 0; + if (d->type == BIOSDISK_TYPE_CD || + (d->type == BIOSDISK_TYPE_HD && biosdisk_int13ext(d->dev))) { + d->flags |= BIOSDISK_INT13EXT; + if (ed != NULL) { + ed->size = sizeof(*ed); + if (biosdisk_getextinfo(d->dev, ed) != 0) + return -1; + } + } + + /* + * If the drive is 2.88MB floppy drive, check that we can actually + * read sector >= 18. If not, assume 1.44MB floppy disk. + */ + if (d->type == BIOSDISK_TYPE_FD && SPT(diskinfo) == 36) { + char buf[512]; + + if (biosdisk_read(d->dev, 0, 0, 18, 1, buf)) { + d->sec = 18; + d->chs_sectors /= 2; + } + } + + return 0; +} + +/* + * Global shared "diskbuf" is used as read ahead buffer. For reading from + * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that + * this buffer doesn't cross a 64K DMA boundary. + */ +static int ra_dev; +static daddr_t ra_end; +static daddr_t ra_first; + +/* + * Because some older BIOSes have bugs in their int13 extensions, we + * only try to use the extended read if the I/O request can't be addressed + * using CHS. + * + * Of course, some BIOSes have bugs in ths CHS read, such as failing to + * function properly if the MBR table has a different geometry than the + * BIOS would generate internally for the device in question, and so we + * provide a way to force the extended on hard disks via a compile-time + * option. + */ +#if defined(FORCE_INT13EXT) +#define NEED_INT13EXT(d, dblk, num) \ + (((d)->dev & 0x80) != 0) +#else +#define NEED_INT13EXT(d, dblk, num) \ + (((d)->type == BIOSDISK_TYPE_CD) || \ + ((d)->type == BIOSDISK_TYPE_HD && \ + ((dblk) + (num)) >= (d)->chs_sectors)) +#endif + +static int +do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf) +{ + + if (NEED_INT13EXT(d, dblk, num)) { + struct { + int8_t size; + int8_t resvd; + int16_t cnt; + int16_t off; + int16_t seg; + int64_t sec; + } ext; + + if (!(d->flags & BIOSDISK_INT13EXT)) + return -1; + ext.size = sizeof(ext); + ext.resvd = 0; + ext.cnt = num; + /* seg:off of physical address */ + ext.off = (int)buf & 0xf; + ext.seg = vtophys(buf) >> 4; + ext.sec = dblk; + + if (biosdisk_extread(d->dev, &ext)) { + (void)biosdisk_reset(d->dev); + return -1; + } + + return ext.cnt; + } else { + int cyl, head, sec, nsec, spc, dblk32; + + dblk32 = (int)dblk; + spc = d->head * d->sec; + cyl = dblk32 / spc; + head = (dblk32 % spc) / d->sec; + sec = dblk32 % d->sec; + nsec = d->sec - sec; + + if (nsec > num) + nsec = num; + + if (biosdisk_read(d->dev, cyl, head, sec, nsec, buf)) { + (void)biosdisk_reset(d->dev); + return -1; + } + + return nsec; + } +} + +/* + * NB if 'cold' is set below not all of the program is loaded, so + * mustn't use data segment, bss, call library functions or do read-ahead. + */ +int +readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold) +{ +#ifdef BOOTXX +#define cold 1 /* collapse out references to diskbufp */ +#endif + while (num) { + int nsec; + + /* check for usable data in read-ahead buffer */ + if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev + || dblk < ra_first || dblk >= ra_end) { + + /* no, read from disk */ + char *trbuf; + int maxsecs; + int retries = BIOSDISK_RETRIES; + + if (cold) { + /* transfer directly to buffer */ + trbuf = buf; + maxsecs = num; + } else { + /* fill read-ahead buffer */ + trbuf = alloc_diskbuf(0); /* no data yet */ + maxsecs = DISKBUFSIZE / d->secsize; + } + + while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) { +#ifdef DISK_DEBUG + if (!cold) + printf("read error dblk %"PRId64"-%"PRId64"\n", + dblk, (dblk + maxsecs - 1)); +#endif + if (--retries >= 0) + continue; + return -1; /* XXX cannot output here if + * (cold) */ + } + if (!cold) { + ra_dev = d->dev; + ra_first = dblk; + ra_end = dblk + nsec; + diskbuf_user = &ra_dev; + } + } else /* can take blocks from end of read-ahead + * buffer */ + nsec = ra_end - dblk; + + if (!cold) { + /* copy data from read-ahead to user buffer */ + if (nsec > num) + nsec = num; + memcpy(buf, + diskbufp + (dblk - ra_first) * d->secsize, + nsec * d->secsize); + } + buf += nsec * d->secsize; + num -= nsec; + dblk += nsec; + } + + return 0; +} + +/* + * Return the number of hard disk drives. + */ +int +get_harddrives(void) +{ + /* + * Some BIOSes are buggy so that they return incorrect number + * of hard drives with int13/ah=8. We read a byte at 0040:0075 + * instead, which is known to be always correct. + */ + int n = 0; + + pvbcopy((void *)0x475, &n, 1); + + return n; +} diff --git a/sys/arch/i386/stand/lib/biosdisk_ll.h b/sys/arch/i386/stand/lib/biosdisk_ll.h new file mode 100644 index 000000000..45ac5895c --- /dev/null +++ b/sys/arch/i386/stand/lib/biosdisk_ll.h @@ -0,0 +1,126 @@ +/* $NetBSD: biosdisk_ll.h,v 1.15 2007/12/25 18:33:34 perry Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * shared by bootsector startup (bootsectmain) and biosdisk.c needs lowlevel + * parts from bios_disk.S + */ + +/* + * Beware that bios_disk.S relies on the offsets of the structure + * members. + */ +struct biosdisk_ll { + int dev; /* BIOS device number */ + int type; /* device type; see below */ + int sec, head, cyl; /* geometry */ + int flags; /* see below */ + int chs_sectors; /* # of sectors addressable by CHS */ + int secsize; /* bytes per sector */ +}; +#define BIOSDISK_INT13EXT 1 /* BIOS supports int13 extension */ + +#define BIOSDISK_TYPE_FD 0 +#define BIOSDISK_TYPE_HD 1 +#define BIOSDISK_TYPE_CD 2 + +/* + * Version 1.x drive parameters from int13 extensions + * - should be supported by every BIOS that supports the extensions. + * Version 3.x parameters allow the drives to be matched properly + * - but are much less likely to be supported. + */ + +struct biosdisk_extinfo { + uint16_t size; /* size of buffer, set on call */ + uint16_t flags; /* flags, see below */ + uint32_t cyl; /* # of physical cylinders */ + uint32_t head; /* # of physical heads */ + uint32_t sec; /* # of physical sectors per track */ + uint64_t totsec; /* total number of sectors */ + uint16_t sbytes; /* # of bytes per sector */ +#if defined(BIOSDISK_EXTINFO_V2) || defined(BIOSDISK_EXTINFO_V3) + /* v2.0 extensions */ + uint32_t edd_cfg; /* EDD configuration parameters */ +#if defined(BIOSDISK_EXTINFO_V3) + /* v3.0 extensions */ + uint16_t devpath_sig; /* 0xbedd if path info present */ +#define EXTINFO_DEVPATH_SIGNATURE 0xbedd + uint8_t devpath_len; /* length from devpath_sig */ + uint8_t fill21[3]; + char host_bus[4]; /* Probably "ISA" or "PCI" */ + char iface_type[8]; /* "ATA", "ATAPI", "SCSI" etc */ + union { + uint8_t ip_8[8]; + uint16_t ip_16[4]; + uint32_t ip_32[2]; + uint64_t ip_64[1]; + } interface_path; +#define ip_isa_iobase ip_16[0]; /* iobase for ISA bus */ +#define ip_pci_bus ip_8[0]; /* PCI bus number */ +#define ip_pci_device ip_8[1]; /* PCI device number */ +#define ip_pci_function ip_8[2]; /* PCI function number */ + union { + uint8_t dp_8[8]; + uint16_t dp_16[4]; + uint32_t dp_32[2]; + uint64_t dp_64[1]; + } device_path; +#define dp_ata_slave dp_8[0]; +#define dp_atapi_slave dp_8[0]; +#define dp_atapi_lun dp_8[1]; +#define dp_scsi_lun dp_8[0]; +#define dp_firewire_guid dp_64[0]; +#define dp_fibrechnl_wwn dp_64[0]; + uint8_t fill40[1]; + uint8_t checksum; /* byte sum from dev_path_sig is 0 */ +#endif /* BIOSDISK_EXTINFO_V3 */ +#endif /* BIOSDISK_EXTINFO_V2 */ +} __packed; + +#define EXTINFO_DMA_TRANS 0x0001 /* transparent DMA boundary errors */ +#define EXTINFO_GEOM_VALID 0x0002 /* geometry in c/h/s in struct valid */ +#define EXTINFO_REMOVABLE 0x0004 /* removable device */ +#define EXTINFO_WRITEVERF 0x0008 /* supports write with verify */ +#define EXTINFO_CHANGELINE 0x0010 /* changeline support */ +#define EXTINFO_LOCKABLE 0x0020 /* device is lockable */ +#define EXTINFO_MAXGEOM 0x0040 /* geometry set to max; no media */ + +#define BIOSDISK_DEFAULT_SECSIZE 512 + +int set_geometry(struct biosdisk_ll *, struct biosdisk_extinfo *); +int readsects(struct biosdisk_ll *, daddr_t, int, char *, int); diff --git a/sys/arch/i386/stand/lib/biosgetrtc.S b/sys/arch/i386/stand/lib/biosgetrtc.S new file mode 100644 index 000000000..af1ec9846 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosgetrtc.S @@ -0,0 +1,58 @@ +/* $NetBSD: biosgetrtc.S,v 1.7 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +ENTRY(biosgetrtc) + pusha + pushl %eax + + xorl %ebx, %ebx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $2, %ah + int $0x1a + jnc ok + movl $-1, %ebx + +ok: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + popl %eax + movb %ch, (%eax) + movb %cl, 1(%eax) + movb %dh, 2(%eax) + movb $0, 3(%eax) + + movl %ebx, 28(%esp) + + popa + ret diff --git a/sys/arch/i386/stand/lib/biosgetsystime.S b/sys/arch/i386/stand/lib/biosgetsystime.S new file mode 100644 index 000000000..984cb0ce1 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosgetsystime.S @@ -0,0 +1,54 @@ +/* $NetBSD: biosgetsystime.S,v 1.3 2011/06/16 13:27:59 joerg Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* Return system time (~18.2Hz ticks since midnight) */ + +ENTRY(biosgetsystime) + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0, %ah + int $0x1a + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + mov %ecx, %eax + shl $16, %eax + movw %dx, %ax + movl %eax, 28(%esp) + + popa + ret diff --git a/sys/arch/i386/stand/lib/biosmca.S b/sys/arch/i386/stand/lib/biosmca.S new file mode 100644 index 000000000..80be1c8fe --- /dev/null +++ b/sys/arch/i386/stand/lib/biosmca.S @@ -0,0 +1,117 @@ +/* $NetBSD: biosmca.S,v 1.4 2003/02/01 14:48:18 dsl Exp $ */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* extracted from netbsd:sys/arch/i386/stand/bios_disk.S */ + +#include + + .data + .globl _C_LABEL(biosmca_ps2model) +_C_LABEL(biosmca_ps2model): .long 0 + + .text +/* +# BIOS call "INT 0x15 Function 0xc0" to read extended sys config info on PS/2 +# Return: no return value +# +# This function initializes biosmca_ps2model with model number as +# identified by BIOS, if the machine is a PS/2 box (i.e. has MCA bus +# instead of ISA). +*/ +ENTRY(biosmca) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + push %ecx + push %edx + push %esi + push %edi + push %eax + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + # zero %ecx + xorl %ecx, %ecx + + xor %ax, %ax + movb $0xc0, %ah # subfunction + int $0x15 + jc back + + # check feature byte 1 if MCA bus present and replaces ISA + movb %es:5(%bx), %al + andb $0x02, %al # bit 1 set means MCA instead of ISA + # see also arch/i386/mca/mca_machdep.c + jnz back + + # save model and submodel bytes to %cx + movb %es:2(%bx), %ch # model (1 byte) + movb %es:3(%bx), %cl # submodel (1 byte) + +back: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + # save model + movl %ecx, _C_LABEL(biosmca_ps2model) + + pop %eax + pop %edi + pop %esi + pop %edx + pop %ecx + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/biosmca.h b/sys/arch/i386/stand/lib/biosmca.h new file mode 100644 index 000000000..d33ade2bf --- /dev/null +++ b/sys/arch/i386/stand/lib/biosmca.h @@ -0,0 +1,31 @@ +/* $NetBSD: biosmca.h,v 1.3 2008/12/14 17:03:43 christos Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void biosmca(void); + +extern int biosmca_ps2model; diff --git a/sys/arch/i386/stand/lib/biosmem.S b/sys/arch/i386/stand/lib/biosmem.S new file mode 100644 index 000000000..4f39622ef --- /dev/null +++ b/sys/arch/i386/stand/lib/biosmem.S @@ -0,0 +1,78 @@ +/* $NetBSD: biosmem.S,v 1.9 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + + .text + +/* get mem below 1M, in kByte */ + +ENTRY(getbasemem) + pusha + + call _C_LABEL(prot_to_real) + .code16 + + int $0x12 + # zero-extend 16-bit result to 32 bits. + movzwl %ax, %eax + + calll _C_LABEL(real_to_prot) + .code32 + + movl %eax, 28(%esp) + popa + ret + +/* get mem above 1M, in kByte */ + +ENTRY(getextmem1) + pusha + + call _C_LABEL(prot_to_real) + .code16 + + movb $0x88,%ah + int $0x15 + + # zero-extend 16-bit result to 32 bits. + movzwl %ax, %eax + + calll _C_LABEL(real_to_prot) + .code32 + + movl %eax, 28(%esp) + popa + ret + diff --git a/sys/arch/i386/stand/lib/biosmemps2.S b/sys/arch/i386/stand/lib/biosmemps2.S new file mode 100644 index 000000000..0b28011c2 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosmemps2.S @@ -0,0 +1,87 @@ +/* $NetBSD: biosmemps2.S,v 1.6 2011/06/16 13:27:59 joerg Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .text + +/* int getextmemp2(void buffer) + call int 15 function 0xc7 - later PS/2s - RETURN MEMORY-MAP INFORMATION + return: 0=OK, nonzero=error + buffer: filled with memory-map table structure +*/ +ENTRY(getextmemps2) + .code32 + movl %eax, %edx + xorl %eax, %eax + pusha + + call _C_LABEL(prot_to_real) + .code16 + + # do int15, function 0xc0 call to discover if C7h is supported + movb $0xc0, %ah + int $0x15 + setc %cl + jc out # 0xc0 not supported if carry set + + # check feature byte 2, bit 4 to see if return memory map is supported + movb %es:6(%bx), %al + andb $0x10, %al + jnz getmem # 0xc7 supported + + # set %cl to indicate failure, and exit + movb $2, %cl + jmp out + +getmem: + # move the parameter to right register + push %ds + movl %edx, %esi + andl $0xf, %esi + shrl $4, %edx + mov %ds, %ax + add %dx, %ax + mov %ax, %ds + + # actually call int15, function 0xc7 now + movb $0xc7, %ah + int $0x15 + setc %cl # save carry + pop %ds + +out: + calll _C_LABEL(real_to_prot) + .code32 + + movb %cl, 28(%esp) + popa + ret diff --git a/sys/arch/i386/stand/lib/biosmemx.S b/sys/arch/i386/stand/lib/biosmemx.S new file mode 100644 index 000000000..041451b3f --- /dev/null +++ b/sys/arch/i386/stand/lib/biosmemx.S @@ -0,0 +1,167 @@ +/* $NetBSD: biosmemx.S,v 1.9 2008/10/14 14:18:11 ad Exp $ */ + +/* + * Copyright (c) 1997, 1999 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + + .text + +/* int getextmem2(int buffer[2]) + return: 0=OK, -1=error + buffer[0]: extmem kBytes below 16M (max 15M/1024) + buffer[1]: extmem above 16M, in 64k units +*/ +ENTRY(getextmem2) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + call _C_LABEL(prot_to_real) + .code16 + + xorl %ebx, %ebx + movl $0xe801, %eax + int $0x15 + pushf + + movw %si, %ax + orw %si, %bx + jz 1f /* if zero use configured values */ + movw %cx, %ax /* k below 16M (max 0x3c00 = 15MB) */ + movw %dx, %bx /* 64k above 16M */ +1: + popf + setc %bl + + calll _C_LABEL(real_to_prot) + .code32 + + movl 8(%ebp), %edi + xorl %eax, %eax + movw %cx, %ax + stosl + movw %dx, %ax + stosl + movb %bl, %al + cbw + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* int getmementry(int *iterator, buffer[5]) + return: 0=ok, else error + buffer[0]: start of memory chunk + buffer[2]: length (bytes) + buffer[4]: type +*/ +ENTRY(getmementry) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %eax + movl 0(%eax), %ebx /* index */ + movl $20, %ecx /* Buffer size */ + movl $0x534d4150, %edx /* "SMAP" */ + movl 12(%ebp), %edi /* buffer address */ + + call _C_LABEL(prot_to_real) + .code16 + + push %di + shrl $4, %edi + mov %ds, %ax + add %di, %ax + mov %ax, %es + pop %di + and $0xf, %di /* buffer addres now in ES:DI */ + + movl $0xe820, %eax /* Some BIOS check EAX value */ + int $0x15 + + setc %cl + + calll _C_LABEL(real_to_prot) + .code32 + + movl 8(%ebp), %eax + movl %ebx, 0(%eax) /* updated index */ + xorl %eax, %eax + movb %cl, %al + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* int biosA20(void) + return: 0=ok, else error +*/ +ENTRY(biosA20) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + call _C_LABEL(prot_to_real) + .code16 + + movl $0x2401, %eax + int $0x15 + setc %cl + + calll _C_LABEL(real_to_prot) + .code32 + + movzbl %cl, %eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/biospci.c b/sys/arch/i386/stand/lib/biospci.c new file mode 100644 index 000000000..d40eddd3a --- /dev/null +++ b/sys/arch/i386/stand/lib/biospci.c @@ -0,0 +1,96 @@ +/* $NetBSD: biospci.c,v 1.5 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * basic PCI functions for libsa needs lowlevel parts from bios_pci.S + */ + +#include + +#include "pcivar.h" + +extern int pcibios_present(int *); +extern int pcibios_finddev(int, int, int, unsigned int *); +extern int pcibios_cfgread(unsigned int, int, int *); +extern int pcibios_cfgwrite(unsigned int, int, int); + +#define PCISIG ('P' | ('C' << 8) | ('I' << 16) | (' ' << 24)) + +int +pcicheck(void) +{ + int ret, sig; + + ret = pcibios_present(&sig); + + if ((ret & 0xff00) || (sig != PCISIG)) + return -1; + + return 0; +} + +int +pcifinddev(int vid, int did, pcihdl_t *handle) +{ + int ret; + + *handle = 0; + + ret = pcibios_finddev(vid, did, 0, handle); + + if (ret) + return -1; + + return 0; +} + +int +pcicfgread(pcihdl_t *handle, int off, int *val) +{ + int ret; + + ret = pcibios_cfgread(*handle, off, val); + + if (ret) + return -1; + + return 0; +} + +int +pcicfgwrite(pcihdl_t *handle, int off, int val) +{ + int ret; + + ret = pcibios_cfgwrite(*handle, off, val); + + if (ret) + return -1; + + return 0; +} diff --git a/sys/arch/i386/stand/lib/biosreboot.S b/sys/arch/i386/stand/lib/biosreboot.S new file mode 100644 index 000000000..315b720af --- /dev/null +++ b/sys/arch/i386/stand/lib/biosreboot.S @@ -0,0 +1,57 @@ +/* $NetBSD: biosreboot.S,v 1.5 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Copyright (c) 1997 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include + + .text + +/* Call INT 19 to do the equivalent of CTL-ALT-DEL */ + +ENTRY(reboot) + pusha + + call _C_LABEL(prot_to_real) + .code16 + + int $0x19 + + /* NOTE: We should never even get past this point. */ + + calll _C_LABEL(real_to_prot) + .code32 + + movl %ebx, 28(%esp) + popa + ret diff --git a/sys/arch/i386/stand/lib/biosvbe.S b/sys/arch/i386/stand/lib/biosvbe.S new file mode 100644 index 000000000..92de9cb32 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosvbe.S @@ -0,0 +1,358 @@ +/* $NetBSD: biosvbe.S,v 1.3 2011/02/20 22:03:13 jakllsch Exp $ */ + +/*- + * Copyright (c) 2009 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 + + .text + +/* + * VESA BIOS Extensions routines + */ + +/* + * Function 00h - Return VBE Controller Information + * + * int biosvbe_info(struct vbeinfoblock *) + * return: VBE call status + */ +ENTRY(biosvbe_info) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %edi /* vbe info block address*/ + + call _C_LABEL(prot_to_real) + .code16 + + push %es + + push %di + shrl $4, %edi + mov %ds, %ax + add %di, %ax + mov %ax, %es + pop %di + and $0xf, %di /* mode info block address now in es:di */ + + movw $0x4f00, %ax /* get vbe info block */ + int $0x10 + + pop %es + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 01h - Return VBE Mode Information + * + * int biosvbe_get_mode_info(int mode, struct modeinfoblock *mi) + * return: VBE call status + */ +ENTRY(biosvbe_get_mode_info) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %ecx /* mode number */ + movl 12(%ebp), %edi /* mode info block address */ + + call _C_LABEL(prot_to_real) + .code16 + + push %es + + push %di + shrl $4, %edi + mov %ds, %ax + add %di, %ax + mov %ax, %es + pop %di + and $0xf, %di /* mode info block address now in es:di */ + + movw $0x4f01, %ax /* get mode info block */ + int $0x10 + + pop %es + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 02h - Set VBE Mode + * + * int biosvbe_set_mode(int mode) + * return: VBE call status + */ +ENTRY(biosvbe_set_mode) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %ebx /* mode number */ + orl $0x4000, %ebx + + call _C_LABEL(prot_to_real) + .code16 + + movw $0x4f02, %ax /* set mode */ + int $0x10 + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 08h - Set/Get DAC Palette Format + * + * int biosvbe_palette_format(int format) + * return: VBE call status + */ +ENTRY(biosvbe_palette_format) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %ebx /* mode number */ + + call _C_LABEL(prot_to_real) + .code16 + + movw $0x4f08, %ax /* get/set palette format */ + int $0x10 + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 09h - Set/Get Palette Data + * + * int biosvbe_palette_data(int mode, int reg, struct paletteentry *) + * return: VBE call status + */ +ENTRY(biosvbe_palette_data) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %ebx /* mode number */ + movl 12(%ebp), %edx /* register */ + movl 16(%ebp), %edi /* palette entry address */ + movl $1, %ecx /* # palette entries to update */ + + call _C_LABEL(prot_to_real) + .code16 + + push %es + + push %di + shrl $4, %edi + mov %ds, %ax + add %di, %ax + mov %ax, %es + pop %di + and $0xf, %di /* palette entry address now in es:di */ + + movw $0x4f09, %ax /* get/set palette entry */ + int $0x10 + + pop %es + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 15h BL=00h - Report VBE/DDC Capabilities + * + * int biosvbe_ddc_caps(void) + * return: VBE/DDC capabilities + */ +ENTRY(biosvbe_ddc_caps) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + call _C_LABEL(prot_to_real) + .code16 + + pushw %es + + xorw %di, %di + movw %di, %es /* es:di == 0:0 */ + + movw $0x4f15, %ax /* display identification extensions */ + mov $0x00, %bx /* report DDC capabilities */ + mov $0x00, %cx /* controller unit number (00h = primary) */ + int $0x10 + + popw %es + + calll _C_LABEL(real_to_prot) + .code32 + + movl %eax,%ecx + movl $0x0000,%eax + andl $0xffff,%ecx + cmpl $0x004f,%ecx + jne 1f + andl $0xffff,%ebx + movl %ebx,%eax +1: + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * Function 15h BL=01h - Read EDID + * + * int biosvbe_ddc_read_edid(int blockno, void *buf) + * return: VBE call status + */ +ENTRY(biosvbe_ddc_read_edid) + pushl %ebp + movl %esp,%ebp + pushl %ebx + pushl %ecx + pushl %edx + push %esi + push %edi + + movl 8(%ebp), %edx /* EDID block number */ + movl 12(%ebp), %edi /* EDID block address */ + + call _C_LABEL(prot_to_real) + .code16 + + push %es + + push %di + shrl $4, %edi + mov %ds, %ax + add %di, %ax + mov %ax, %es + pop %di + and $0xf, %di /* EDID block address now in es:di */ + + movw $0x4f15, %ax /* display identification extensions */ + mov $0x01, %bx /* read EDID */ + mov $0x00, %cx /* controller unit number (00h = primary) */ + int $0x10 + + pop %es + + calll _C_LABEL(real_to_prot) + .code32 + + andl $0xffff,%eax + + pop %edi + pop %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + diff --git a/sys/arch/i386/stand/lib/biosvideomode.S b/sys/arch/i386/stand/lib/biosvideomode.S new file mode 100644 index 000000000..c3b0df880 --- /dev/null +++ b/sys/arch/i386/stand/lib/biosvideomode.S @@ -0,0 +1,65 @@ +/* $NetBSD: biosvideomode.S,v 1.3 2003/04/16 13:49:21 dsl Exp $ */ + +/* + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + + .text + +ENTRY(biosvideomode) + pushl %ebp + movl %esp,%ebp + pushl %ebx + push %esi + push %edi + + call _C_LABEL(prot_to_real) + .code16 + + movb $0, %ah + movb $2, %al + int $0x10 + # zero-extend 16-bit result to 32 bits. + movl $0, %ebx + movw %ax,%bx + + calll _C_LABEL(real_to_prot) + .code32 + + movl %ebx, %eax + + pop %edi + pop %esi + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/boot_params.S b/sys/arch/i386/stand/lib/boot_params.S new file mode 100644 index 000000000..5309aff13 --- /dev/null +++ b/sys/arch/i386/stand/lib/boot_params.S @@ -0,0 +1,15 @@ +/* $NetBSD: boot_params.S,v 1.6 2010/01/17 14:54:44 drochner Exp $ */ + +/* Default boot parameters - must match struct x86_boot_params in bootblock.h */ + +#ifdef BOOTPARAM_DEFFLAGS + .long BOOTPARAM_DEFFLAGS +#else + .long 0x0 +#endif + .long 5 /* timeout in seconds */ + .long 0 /* console device 0 => CONSDEV_PC */ + .long 9600 /* serial baud rate */ + .space 16 /* md5 boot password */ + .space 64 /* keyboard xlat map */ + .long 0 /* console ioaddr */ diff --git a/sys/arch/i386/stand/lib/bootinfo.c b/sys/arch/i386/stand/lib/bootinfo.c new file mode 100644 index 000000000..84032e0bf --- /dev/null +++ b/sys/arch/i386/stand/lib/bootinfo.c @@ -0,0 +1,45 @@ +/* $NetBSD: bootinfo.c,v 1.5 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "libi386.h" +#include "bootinfo.h" + +struct bootinfo *bootinfo; + +void +bi_add(struct btinfo_common *what, int type, int size) +{ + what->len = size; + what->type = type; + + if (bootinfo) + bootinfo->entry[bootinfo->nentries++] = vtophys(what); +} diff --git a/sys/arch/i386/stand/lib/bootinfo.h b/sys/arch/i386/stand/lib/bootinfo.h new file mode 100644 index 000000000..df1d5aa3a --- /dev/null +++ b/sys/arch/i386/stand/lib/bootinfo.h @@ -0,0 +1,48 @@ +/* $NetBSD: bootinfo.h,v 1.9 2006/01/25 18:28:26 christos Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +struct bootinfo { + int nentries; + physaddr_t entry[1]; +}; + +extern struct bootinfo *bootinfo; + +#define BI_ALLOC(max) (bootinfo = alloc(sizeof(struct bootinfo) \ + + ((max) - 1) * sizeof(physaddr_t))) \ + ->nentries = 0 + +#define BI_FREE() dealloc(bootinfo, 0) + +#define BI_ADD(x, type, size) bi_add((struct btinfo_common *)(x), type, size) + +void bi_add(struct btinfo_common *, int, int); +void bi_getbiosgeom(void); +void bi_getmemmap(void); diff --git a/sys/arch/i386/stand/lib/bootinfo_biosgeom.c b/sys/arch/i386/stand/lib/bootinfo_biosgeom.c new file mode 100644 index 000000000..43e8784d7 --- /dev/null +++ b/sys/arch/i386/stand/lib/bootinfo_biosgeom.c @@ -0,0 +1,181 @@ +/* $NetBSD: bootinfo_biosgeom.c,v 1.21 2010/12/25 01:19:33 jakllsch Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include +#include + +#include "libi386.h" +#include "biosdisk_ll.h" +#include "bootinfo.h" + +#ifdef BIOSDISK_EXTINFO_V3 +static struct { + char *name; + int flag; +} bus_names[] = { {"ISA", BI_GEOM_BUS_ISA}, + {"PCI", BI_GEOM_BUS_PCI}, + {NULL, BI_GEOM_BUS_OTHER} }; +static struct { + char *name; + int flag; +} iface_names[] = { {"ATA", BI_GEOM_IFACE_ATA}, + {"ATAPI", BI_GEOM_IFACE_ATAPI}, + {"SCSI", BI_GEOM_IFACE_SCSI}, + {"USB", BI_GEOM_IFACE_USB}, + {"1394", BI_GEOM_IFACE_1394}, + {"FIBRE", BI_GEOM_IFACE_FIBRE}, + {NULL, BI_GEOM_IFACE_OTHER} }; +#endif + +void +bi_getbiosgeom(void) +{ + struct btinfo_biosgeom *bibg; + int i, j, nvalid; + int nhd; + unsigned int cksum; + struct biosdisk_ll d; + struct biosdisk_extinfo ed; + char buf[BIOSDISK_DEFAULT_SECSIZE]; + + nhd = get_harddrives(); +#ifdef GEOM_DEBUG + printf("nhd %d\n", nhd); +#endif + + bibg = alloc(sizeof(struct btinfo_biosgeom) + + (nhd - 1) * sizeof(struct bi_biosgeom_entry)); + if (bibg == NULL) + return; + + for (i = nvalid = 0; i < MAX_BIOSDISKS && nvalid < nhd; i++) { + + d.dev = 0x80 + i; + + if (set_geometry(&d, &ed)) + continue; + memset(&bibg->disk[nvalid], 0, sizeof(bibg->disk[nvalid])); + + bibg->disk[nvalid].sec = d.sec; + bibg->disk[nvalid].head = d.head; + bibg->disk[nvalid].cyl = d.cyl; + bibg->disk[nvalid].dev = d.dev; + + if (readsects(&d, 0, 1, buf, 0)) { + bibg->disk[nvalid].flags |= BI_GEOM_INVALID; + nvalid++; + continue; + } + +#ifdef GEOM_DEBUG + printf("#%d: %x: C %d H %d S %d\n", nvalid, + d.dev, d.cyl, d.head, d.sec); + printf(" sz %d fl %x cyl %d head %d sec %d totsec %"PRId64" sbytes %d\n", + ed.size, ed.flags, ed.cyl, ed.head, ed.sec, + ed.totsec, ed.sbytes); +#endif + + if (d.flags & BIOSDISK_INT13EXT) { + bibg->disk[nvalid].totsec = ed.totsec; + bibg->disk[nvalid].flags |= BI_GEOM_EXTINT13; + } +#ifdef BIOSDISK_EXTINFO_V3 +#ifdef GEOM_DEBUG + printf(" edd_cfg %x, sig %x, len %x, bus %s type %s\n", + ed.edd_cfg, ed.devpath_sig, ed.devpath_len, + ed.host_bus, ed.iface_type); +#endif + + /* The v3.0 stuff will help identify the disks */ + if (ed.size >= offsetof(struct biosdisk_ext13info, checksum) + && ed.devpath_sig == EXTINFO_DEVPATH_SIGNATURE) { + char *cp; + + for (cp = (void *)&ed.devpath_sig, cksum = 0; + cp <= (char *)&ed.checksum; cp++) { + cksum += *cp; + } + if ((cksum & 0xff) != 0) + bibg->disk[nvalid].flags |= BI_GEOM_BADCKSUM; +#ifdef GEOM_DEBUG + printf("checksum %x\n", cksum & 0xff); +#endif + for (j = 0; ; j++) { + cp = bus_names[j].name; + if (cp == NULL) + break; + if (strncmp(cp, ed.host_bus, + sizeof(ed.host_bus)) == 0) + break; + } +#ifdef GEOM_DEBUG + printf("bus %s (%x)\n", cp ? cp : "null", + bus_names[j].flag); +#endif + bibg->disk[nvalid].flags |= bus_names[j].flag; + for (j = 0; ; j++) { + cp = iface_names[j].name; + if (cp == NULL) + break; + if (strncmp(cp, ed.iface_type, + sizeof(ed.iface_type)) == 0) + break; + } + bibg->disk[nvalid].flags |= iface_names[j].flag; + /* Dump raw interface path and device path */ + bibg->disk[nvalid].interface_path = + ed.interface_path.ip_32[0]; + bibg->disk[nvalid].device_path = + ed.device_path.dp_64[0]; +#ifdef GEOM_DEBUG + printf("device %s (%x) interface %x path %llx\n", + cp ? cp : "null", + iface_names[j].flag, + ed.interface_path.ip_32[0], + ed.device_path.dp_64[0]); +#endif + } +#endif + + for (j = 0, cksum = 0; j < BIOSDISK_DEFAULT_SECSIZE; j++) + cksum += buf[j]; + bibg->disk[nvalid].cksum = cksum; + memcpy(bibg->disk[nvalid].dosparts, &buf[MBR_PART_OFFSET], + sizeof(bibg->disk[nvalid].dosparts)); + nvalid++; + } + + bibg->num = nvalid; + + BI_ADD(bibg, BTINFO_BIOSGEOM, sizeof(struct btinfo_biosgeom) + + nvalid * sizeof(struct bi_biosgeom_entry)); +} diff --git a/sys/arch/i386/stand/lib/bootinfo_memmap.c b/sys/arch/i386/stand/lib/bootinfo_memmap.c new file mode 100644 index 000000000..ee69c52c1 --- /dev/null +++ b/sys/arch/i386/stand/lib/bootinfo_memmap.c @@ -0,0 +1,61 @@ +/* $NetBSD: bootinfo_memmap.c,v 1.5 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1999 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "libi386.h" +#include "bootinfo.h" + +extern int getmementry(int *, int *); + +void +bi_getmemmap(void) +{ + int buf[5], i, nranges, n; + struct btinfo_memmap *bimm; + + nranges = 0; + i = 0; + do { + if (getmementry(&i, buf)) + break; + nranges++; + } while (i); + + bimm = alloc(sizeof(struct btinfo_memmap) + + (nranges - 1) * sizeof(struct bi_memmap_entry)); + + i = 0; + for (n = 0; n < nranges; n++) { + getmementry(&i, buf); + memcpy(&bimm->entry[n], buf, sizeof(struct bi_memmap_entry)); + } + bimm->num = nranges; + + BI_ADD(bimm, BTINFO_MEMMAP, sizeof(struct btinfo_memmap) + + (nranges - 1) * sizeof(struct bi_memmap_entry)); +} diff --git a/sys/arch/i386/stand/lib/bootmenu.c b/sys/arch/i386/stand/lib/bootmenu.c new file mode 100644 index 000000000..038d12648 --- /dev/null +++ b/sys/arch/i386/stand/lib/bootmenu.c @@ -0,0 +1,386 @@ +/* $NetBSD: bootmenu.c,v 1.10 2011/08/18 13:20:04 christos Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SMALL + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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=:". If the + * description is empty ("menu=:)", + * then re-use the command as the description. + * Note that the command may contain embedded + * colons. + */ + if (cmenu >= MAXMENU) + continue; + bootconf.desc[cmenu] = value; + for (v2 = value; *v2 && *v2 != ':'; v2++) + continue; + if (*v2) { + *v2++ = 0; + bootconf.command[cmenu] = v2; + if (! *value) + bootconf.desc[cmenu] = v2; + cmenu++; + } else { + /* No delimiter means invalid line */ + bootconf.desc[cmenu] = NULL; + } + } else if (!strncmp(key, "banner", 6)) { + if (cbanner < MAXBANNER) + bootconf.banner[cbanner++] = value; + } else if (!strncmp(key, "timeout", 7)) { + if (!isnum(*value)) + bootconf.timeout = -1; + else + bootconf.timeout = atoi(value); + } else if (!strncmp(key, "default", 7)) { + bootconf.def = atoi(value) - 1; + } else if (!strncmp(key, "consdev", 7)) { + bootconf.consdev = value; + } else if (!strncmp(key, "load", 4)) { + module_add(value); + } else if (!strncmp(key, "format", 6)) { + printf("value:%c\n", *value); + switch (*value) { + case 'a': + case 'A': + bootconf.menuformat = MENUFORMAT_AUTO; + break; + + case 'n': + case 'N': + case 'd': + case 'D': + bootconf.menuformat = MENUFORMAT_NUMBER; + break; + + case 'l': + case 'L': + bootconf.menuformat = MENUFORMAT_LETTER; + break; + } + } else if (!strncmp(key, "clear", 5)) { + bootconf.clear = !!atoi(value); + } else if (!strncmp(key, "userconf", 8)) { + userconf_add(value); + } + } + switch (bootconf.menuformat) { + case MENUFORMAT_AUTO: + if (cmenu > 9 && bootconf.timeout > 0) + bootconf.menuformat = MENUFORMAT_LETTER; + else + bootconf.menuformat = MENUFORMAT_NUMBER; + break; + + case MENUFORMAT_NUMBER: + if (cmenu > 9 && bootconf.timeout > 0) + cmenu = 9; + break; + } + + bootconf.nummenu = cmenu; + if (bootconf.def < 0) + bootconf.def = 0; + if (bootconf.def >= cmenu) + bootconf.def = cmenu - 1; +} + +/* + * doboottypemenu will render the menu and parse any user input + */ +static int +getchoicefrominput(char *input, int def) +{ + int choice, usedef; + + choice = -1; + usedef = 0; + + if (*input == '\0' || *input == '\r' || *input == '\n') { + choice = def; + usedef = 1; + } else if (*input >= 'A' && *input < bootconf.nummenu + 'A') + choice = (*input) - 'A'; + else if (*input >= 'a' && *input < bootconf.nummenu + 'a') + choice = (*input) - 'a'; + else if (isnum(*input)) { + choice = atoi(input) - 1; + if (choice < 0 || choice >= bootconf.nummenu) + choice = -1; + } + + if (bootconf.menuformat != MENUFORMAT_LETTER && + !isnum(*input) && !usedef) + choice = -1; + + return choice; +} + +void +doboottypemenu(void) +{ + int choice; + char input[80], *ic, *oc; + + printf("\n"); + /* Display menu */ + if (bootconf.menuformat == MENUFORMAT_LETTER) { + for (choice = 0; choice < bootconf.nummenu; choice++) + printf(" %c. %s\n", choice + 'A', + bootconf.desc[choice]); + } else { + /* Can't use %2d format string with libsa */ + for (choice = 0; choice < bootconf.nummenu; choice++) + printf(" %s%d. %s\n", + (choice < 9) ? " " : "", + choice + 1, + bootconf.desc[choice]); + } + choice = -1; + for (;;) { + input[0] = '\0'; + + if (bootconf.timeout < 0) { + if (bootconf.menuformat == MENUFORMAT_LETTER) + printf("\nOption: [%c]:", + bootconf.def + 'A'); + else + printf("\nOption: [%d]:", + bootconf.def + 1); + + gets(input); + choice = getchoicefrominput(input, bootconf.def); + } else if (bootconf.timeout == 0) + choice = bootconf.def; + else { + printf("\nChoose an option; RETURN for default; " + "SPACE to stop countdown.\n"); + if (bootconf.menuformat == MENUFORMAT_LETTER) + printf("Option %c will be chosen in ", + bootconf.def + 'A'); + else + printf("Option %d will be chosen in ", + bootconf.def + 1); + input[0] = awaitkey(bootconf.timeout, 1); + input[1] = '\0'; + choice = getchoicefrominput(input, bootconf.def); + /* If invalid key pressed, drop to menu */ + if (choice == -1) + bootconf.timeout = -1; + } + if (choice < 0) + continue; + if (!strcmp(bootconf.command[choice], "prompt") && + ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 || + check_password((char *)boot_params.bp_password))) { + printf("type \"?\" or \"help\" for help.\n"); + bootmenu(); /* does not return */ + } else { + ic = bootconf.command[choice]; + /* Split command string at ; into separate commands */ + do { + oc = input; + /* Look for ; separator */ + for (; *ic && *ic != COMMAND_SEPARATOR; ic++) + *oc++ = *ic; + if (*input == '\0') + continue; + /* Strip out any trailing spaces */ + oc--; + for (; *oc == ' ' && oc > input; oc--); + *++oc = '\0'; + if (*ic == COMMAND_SEPARATOR) + ic++; + /* Stop silly command strings like ;;; */ + if (*input != '\0') + docommand(input); + /* Skip leading spaces */ + for (; *ic == ' '; ic++); + } while (*ic); + } + + } +} + +#endif /* !SMALL */ diff --git a/sys/arch/i386/stand/lib/bootmenu.h b/sys/arch/i386/stand/lib/bootmenu.h new file mode 100644 index 000000000..0a2053ddf --- /dev/null +++ b/sys/arch/i386/stand/lib/bootmenu.h @@ -0,0 +1,53 @@ +/* $NetBSD: bootmenu.h,v 1.2 2008/12/13 23:30:54 christos Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BOOTMENU_H +#define _BOOTMENU_H + +#define BOOTCONF "boot.cfg" +#define MAXMENU 20 +#define MAXBANNER 12 +#define COMMAND_SEPARATOR ';' + +void parsebootconf(const char *); +void doboottypemenu(void); +int atoi(const char *); + +struct bootconf_def { + char *banner[MAXBANNER]; /* Banner text */ + char *command[MAXMENU]; /* Menu commands per entry*/ + char *consdev; /* Console device */ + int def; /* Default menu option */ + char *desc[MAXMENU]; /* Menu text per entry */ + int nummenu; /* Number of menu items */ + int timeout; /* Timeout in seconds */ + int menuformat; /* Print letters instead of numbers? */ + int clear; /* Clear the screen? */ +} extern bootconf; + +#endif /* !_BOOTMENU_H */ diff --git a/sys/arch/i386/stand/lib/bootmod.h b/sys/arch/i386/stand/lib/bootmod.h new file mode 100644 index 000000000..6be56535d --- /dev/null +++ b/sys/arch/i386/stand/lib/bootmod.h @@ -0,0 +1,45 @@ +/* $NetBSD: bootmod.h,v 1.5 2011/11/28 07:56:54 tls Exp $ */ + +/*- + * Copyright (c) 2008 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BOOTMOD_H +#define _BOOTMOD_H + +typedef struct boot_module { + char *bm_path; + ssize_t bm_len; + uint8_t bm_type; +#define BM_TYPE_KMOD 0x00 +#define BM_TYPE_IMAGE 0x01 +#define BM_TYPE_RND 0x02 + struct boot_module *bm_next; +} boot_module_t; + +extern boot_module_t *boot_modules; +extern bool boot_modules_enabled; + +#endif /* !_BOOTMOD_H */ diff --git a/sys/arch/i386/stand/lib/comio.S b/sys/arch/i386/stand/lib/comio.S new file mode 100644 index 000000000..4ac914968 --- /dev/null +++ b/sys/arch/i386/stand/lib/comio.S @@ -0,0 +1,148 @@ +/* $NetBSD: comio.S,v 1.4 2003/04/16 14:23:11 dsl Exp $ */ + +/* serial console handling + modelled after code in FreeBSD:sys/i386/boot/netboot/start2.S + */ + +#include + + .text + +/************************************************************************** +INIT - Initialization (com number) +**************************************************************************/ +ENTRY(cominit) + push %ebp + mov %esp,%ebp + push %ebx + push %edx + push %esi + push %edi + + movl 8(%ebp), %edx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + # Initialize the serial port (dl) to 9600 baud, 8N1. + movb $0xe3, %al + movb $0, %ah + int $0x14 + mov %ax,%bx + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + xor %eax,%eax + mov %bx,%ax + + pop %edi + pop %esi + pop %edx + pop %ebx + pop %ebp + ret + +/************************************************************************** +PUTC - Print a character (char, com number) +**************************************************************************/ +ENTRY(computc) + push %ebp + mov %esp,%ebp + push %ecx + push %ebx + push %edx + push %esi + push %edi + + movb 8(%ebp),%cl + movl 12(%ebp),%edx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb %cl,%al + movb $0x01, %ah + int $0x14 + + movb %ah,%bl + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + xor %eax,%eax + movb %bl,%al + + pop %edi + pop %esi + pop %edx + pop %ebx + pop %ecx + pop %ebp + ret + +/************************************************************************** +GETC - Get a character (com number) +**************************************************************************/ +ENTRY(comgetc) + push %ebp + mov %esp,%ebp + push %ebx + push %edx + push %esi + push %edi + + movl 8(%ebp),%edx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x02, %ah + int $0x14 + mov %ax, %bx + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + xor %eax,%eax + mov %bx,%ax + + pop %edi + pop %esi + pop %edx + pop %ebx + pop %ebp + ret + +/************************************************************************** +ISKEY - Check for keyboard interrupt (com number) +**************************************************************************/ +ENTRY(comstatus) + push %ebp + mov %esp,%ebp + push %ebx + push %edx + push %esi + push %edi + + movl 8(%ebp),%edx + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x03, %ah + int $0x14 + mov %ax,%bx + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + xor %eax,%eax + mov %bx,%ax + + pop %edi + pop %esi + pop %edx + pop %ebx + pop %ebp + ret diff --git a/sys/arch/i386/stand/lib/comio_direct.c b/sys/arch/i386/stand/lib/comio_direct.c new file mode 100644 index 000000000..e74621054 --- /dev/null +++ b/sys/arch/i386/stand/lib/comio_direct.c @@ -0,0 +1,243 @@ +/* $NetBSD: comio_direct.c,v 1.10 2008/12/14 18:46:33 christos Exp $ */ + +/*- + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * Charles M. Hannum. All rights reserved. + * + * Taken from sys/dev/isa/com.c and integrated into standalone boot + * programs by Martin Husemann. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)com.c 7.5 (Berkeley) 5/16/91 + */ + +#include +#include +#include +#include +#include "comio_direct.h" +#include "libi386.h" + +/* preread buffer for xon/xoff handling */ +#define XON 0x11 +#define XOFF 0x13 +#define SERBUFSIZE 16 +static u_char serbuf[SERBUFSIZE]; +static int serbuf_read = 0; +static int serbuf_write = 0; +static int stopped = 0; + +#define ISSET(t,f) ((t) & (f)) + +#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ +#define RATE_9600 divrnd((COM_FREQ / 16), 9600) + +/* + * calculate divisor for a given speed + */ +static int +comspeed(long speed) +{ + int x, err; + + if (speed <= 0) + speed = 9600; + x = divrnd((COM_FREQ / 16), speed); + if (x <= 0) + return RATE_9600; + err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000; + if (err < 0) + err = -err; + if (err > COM_TOLERANCE) + return RATE_9600; + return x; +} + +/* + * get a character + */ +int +comgetc_d(int combase) +{ + u_char stat, c; + + if (serbuf_read != serbuf_write) { + c = serbuf[serbuf_read++]; + if (serbuf_read >= SERBUFSIZE) + serbuf_read = 0; + return c; + } + + for (;;) { + while (!ISSET(stat = inb(combase + com_lsr), LSR_RXRDY)) + continue; + c = inb(combase + com_data); + inb(combase + com_iir); + if (c != XOFF) { + stopped = 0; + break; /* got a real char, deliver it... */ + } + stopped = 1; + } + return c; +} + +/* + * output a character, return nonzero on success + */ +int +computc_d(int c, int combase) +{ + u_char stat; + int timo; + + /* check for old XOFF */ + while (stopped) + comgetc_d(combase); /* wait for XON */ + + /* check for new XOFF */ + if (comstatus_d(combase)) { + int c = comgetc_d(combase); /* XOFF handled in comgetc_d */ + /* stuff char into preread buffer */ + serbuf[serbuf_write++] = c; + if (serbuf_write >= SERBUFSIZE) + serbuf_write = 0; + } + + /* wait for any pending transmission to finish */ + timo = 50000; + while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY) + && --timo) + continue; + if (timo == 0) return 0; + outb(combase + com_data, c); + /* wait for this transmission to complete */ + timo = 1500000; + while (!ISSET(stat = inb(combase + com_lsr), LSR_TXRDY) + && --timo) + continue; + if (timo == 0) return 0; + /* clear any interrupts generated by this transmission */ + inb(combase + com_iir); + + return 1; +} + +/* + * Initialize UART to known state. + */ +int +cominit_d(int combase, int speed) +{ + int rate, err; + + serbuf_read = 0; + serbuf_write = 0; + + outb(combase + com_cfcr, LCR_DLAB); + if (speed == 0) { + /* Try to determine the current baud rate */ + rate = inb(combase + com_dlbl) | inb(combase + com_dlbh) << 8; + if (rate == 0) + rate = RATE_9600; + speed = divrnd((COM_FREQ / 16), rate); + err = speed - (speed + 150)/300 * 300; + speed -= err; + if (err < 0) + err = -err; + if (err > 50) + speed = 9600; + } + rate = comspeed(speed); + outb(combase + com_dlbl, rate); + outb(combase + com_dlbh, rate >> 8); + outb(combase + com_cfcr, LCR_8BITS); + outb(combase + com_mcr, MCR_DTR | MCR_RTS); + outb(combase + com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); + outb(combase + com_ier, 0); + + return speed; +} + +/* + * return nonzero if input char available, do XON/XOFF handling + */ +int +comstatus_d(int combase) +{ + /* check if any preread input is already there */ + if (serbuf_read != serbuf_write) return 1; + + /* check for new stuff on the port */ + if (ISSET(inb(combase + com_lsr), LSR_RXRDY)) { + /* this could be XOFF, which we would swallow, so we can't + claim there is input available... */ + int c = inb(combase + com_data); + inb(combase + com_iir); + if (c == XOFF) { + stopped = 1; + } else { + /* stuff char into preread buffer */ + serbuf[serbuf_write++] = c; + if (serbuf_write >= SERBUFSIZE) + serbuf_write = 0; + return 1; + } + } + + return 0; /* nothing out there... */ +} diff --git a/sys/arch/i386/stand/lib/comio_direct.h b/sys/arch/i386/stand/lib/comio_direct.h new file mode 100644 index 000000000..c4f95676a --- /dev/null +++ b/sys/arch/i386/stand/lib/comio_direct.h @@ -0,0 +1,6 @@ +/* $NetBSD: comio_direct.h,v 1.4 2005/11/11 22:25:09 dsl Exp $ */ + +int cominit_d(int, int); +int computc_d(int, int); +int comgetc_d(int); +int comstatus_d(int); diff --git a/sys/arch/i386/stand/lib/conio.S b/sys/arch/i386/stand/lib/conio.S new file mode 100644 index 000000000..dd04a790f --- /dev/null +++ b/sys/arch/i386/stand/lib/conio.S @@ -0,0 +1,126 @@ +/* $NetBSD: conio.S,v 1.7 2011/06/16 13:27:59 joerg Exp $ */ + +/* PC console handling + originally from: FreeBSD:sys/i386/boot/netboot/start2.S + */ + +#include + + .text + +/************************************************************************** +CLR - Clear screen +**************************************************************************/ +ENTRY(conclr) + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + /* Clear screen. */ + movw $0x0600, %ax + movw $0x0700, %bx + xorw %cx, %cx + movw $0x184f, %dx /* 80x25 */ + int $0x10 + + /* Home cursor. */ + movb $0x02, %ah + xorw %bx, %bx + xorw %dx, %dx + int $0x10 + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + popa + ret + +/************************************************************************** +PUTC - Print a character +**************************************************************************/ +ENTRY(conputc) + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movw $1,%bx + movb $0x0e,%ah + movb %al, %cl + int $0x10 + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + popa + ret + +/************************************************************************** +GETC - Get a character +**************************************************************************/ +ENTRY(congetc) + xorl %eax, %eax + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x0,%ah + int $0x16 + movb %al,%bl + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movb %bl, 28(%esp) + + popa + ret + +/************************************************************************** +ISSHIFT - Check for keyboard interrupt; via shift key +**************************************************************************/ +ENTRY(conisshift) + xorl %eax, %eax + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + xor %bx,%bx + movb $0x2,%ah + int $0x16 + testb $3,%al + setnz %bl + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movb %bl, 28(%esp) + + popa + ret + +/************************************************************************** +ISKEY - Check for keyboard input +**************************************************************************/ +ENTRY(coniskey) + xorl %eax, %eax + pusha + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + xor %bx,%bx + movb $0x1,%ah + int $0x16 + setnz %bl + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movb %bl, 28(%esp) + + popa + ret diff --git a/sys/arch/i386/stand/lib/cpufunc.S b/sys/arch/i386/stand/lib/cpufunc.S new file mode 100644 index 000000000..11570d1f5 --- /dev/null +++ b/sys/arch/i386/stand/lib/cpufunc.S @@ -0,0 +1,152 @@ +/* $NetBSD: cpufunc.S,v 1.4 2011/06/08 16:03:42 joerg Exp $ */ + +/*- + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +NENTRY(x86_read_psl) + pushfl + popl %eax + ret + +NENTRY(x86_write_psl) + movl 4(%esp), %eax + pushl %eax + popfl + ret + +NENTRY(x86_disable_intr) + cli + ret + +NENTRY(x86_enable_intr) + sti + ret + +NENTRY(inb) + movl 4(%esp), %edx + xorl %eax, %eax + inb %dx, %al + ret + +NENTRY(insb) + pushl %edi + movl 8(%esp), %edx + movl 12(%esp), %edi + movl 16(%esp), %ecx + cld + rep + insb + popl %edi + ret + +NENTRY(inw) + movl 4(%esp), %edx + xorl %eax, %eax + inw %dx, %ax + ret + +NENTRY(insw) + pushl %edi + movl 8(%esp), %edx + movl 12(%esp), %edi + movl 16(%esp), %ecx + cld + rep + insw + popl %edi + ret + +NENTRY(inl) + movl 4(%esp), %edx + inl %dx, %eax + ret + +NENTRY(insl) + pushl %edi + movl 8(%esp), %edx + movl 12(%esp), %edi + movl 16(%esp), %ecx + cld + rep + insl + popl %edi + ret + +NENTRY(outb) + movl 4(%esp), %edx + movl 8(%esp), %eax + outb %al, %dx + ret + +NENTRY(outsb) + pushl %esi + movl 8(%esp), %edx + movl 12(%esp), %esi + movl 16(%esp), %ecx + cld + rep + outsb + popl %esi + ret + +NENTRY(outw) + movl 4(%esp), %edx + movl 8(%esp), %eax + outw %ax, %dx + ret + +NENTRY(outsw) + pushl %esi + movl 8(%esp), %edx + movl 12(%esp), %esi + movl 16(%esp), %ecx + cld + rep + outsw + popl %esi + ret + +NENTRY(outl) + movl 4(%esp), %edx + movl 8(%esp), %eax + outl %eax, %dx + ret + +NENTRY(outsl) + pushl %esi + movl 8(%esp), %edx + movl 12(%esp), %esi + movl 16(%esp), %ecx + cld + rep + outsl + popl %esi + ret diff --git a/sys/arch/i386/stand/lib/cpufunc.h b/sys/arch/i386/stand/lib/cpufunc.h new file mode 100644 index 000000000..856a3f187 --- /dev/null +++ b/sys/arch/i386/stand/lib/cpufunc.h @@ -0,0 +1,49 @@ +/* $NetBSD: cpufunc.h,v 1.2 2008/04/28 20:23:25 martin Exp $ */ + +/*- + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +void x86_disable_intr(void); +void x86_enable_intr(void); +u_long x86_read_psl(void); +void x86_write_psl(u_long); + +u_int8_t inb(unsigned); +void insb(unsigned, void *, int); +uint16_t inw(unsigned); +void insw(unsigned, void *, int); +uint32_t inl(unsigned); +void insl(unsigned, void *, int); + +void outb(unsigned, uint8_t); +void outsb(unsigned, void *, int); +void outw(unsigned, uint16_t); +void outsw(unsigned, void *, int); +void outl(unsigned, uint32_t); +void outsl(unsigned, void *, int); diff --git a/sys/arch/i386/stand/lib/crt/dos/doscommain.c b/sys/arch/i386/stand/lib/crt/dos/doscommain.c new file mode 100644 index 000000000..93dc95488 --- /dev/null +++ b/sys/arch/i386/stand/lib/crt/dos/doscommain.c @@ -0,0 +1,119 @@ +/* $NetBSD: doscommain.c,v 1.6 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* argument line processing for DOS .COM programs */ + +#include + +/* The Program Segment Prefix */ + +static struct psp{ + char mist1[0x2c]; + short envseg; + char mist2[0x80-2-0x2c]; + char cmdlen; + char cmd[127]; +} *PSP = (struct psp*)0; + +static char* argv[64]; /* theor max */ + +static int whitespace(char); + +static int +whitespace(char c) +{ + if ((c == '\0') || (c == ' ') || (c == '\t') + || (c == '\r') || (c == '\n')) + return (1); + return 0; +} + +enum state {skipping, doing_arg, doing_long_arg}; + +/* build argv/argc, start real main() */ +int doscommain(void); +extern int main(int, char**); + +int +doscommain(void) +{ + int argc, i; + enum state s; + + argv[0] = "???"; /* we don't know */ + argc = 1; + s = skipping; + + for (i = 0; i < PSP->cmdlen; i++){ + + if (whitespace(PSP->cmd[i])) { + if (s == doing_arg) { + /* end of argument word */ + PSP->cmd[i] = '\0'; + s = skipping; + } + continue; + } + + if (PSP->cmd[i] == '"') { + /* start or end long arg + * (end only if next char is whitespace) + * XXX but '" ' cannot be in argument + */ + switch (s) { + case skipping: + /* next char begins new argument word */ + argv[argc++] = &PSP->cmd[i + 1]; + s = doing_long_arg; + break; + case doing_long_arg: + if (whitespace(PSP->cmd[i + 1])) { + PSP->cmd[i] = '\0'; + s = skipping; + } + case doing_arg: + /* ignore in the middle of arguments */ + default: + break; + } + continue; + } + + /* all other characters */ + if (s == skipping) { + /* begin new argument word */ + argv[argc++] = &PSP->cmd[i]; + s = doing_arg; + } + } + if (s != skipping) + PSP->cmd[i] = '\0'; /* to be sure */ + + /* start real main() */ + return main(argc, argv); +} diff --git a/sys/arch/i386/stand/lib/crt/dos/start_dos.S b/sys/arch/i386/stand/lib/crt/dos/start_dos.S new file mode 100644 index 000000000..38eb43ad9 --- /dev/null +++ b/sys/arch/i386/stand/lib/crt/dos/start_dos.S @@ -0,0 +1,620 @@ +/* $NetBSD: start_dos.S,v 1.10 2010/12/20 01:12:44 jakllsch Exp $ */ + +/* + * startup for DOS .COM programs + * with input from: + * netbsd:sys/arch/i386/boot/start.S + * Tor Egge's patches for NetBSD boot (pr port-i386/1002) + * freebsd:sys/i386/boot/netboot/start2.S + * XMS support by Martin Husemann + */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include + + +CR0_PE = 0x1 + + .data + .globl _C_LABEL(ourseg) +_C_LABEL(ourseg): + .long 0 + +/************************************************************************** +GLOBAL DESCRIPTOR TABLE +**************************************************************************/ +#ifdef __ELF__ + .align 16 +#else + .align 4 +#endif +gdt: + .word 0, 0 + .byte 0, 0x00, 0x00, 0 + +#ifdef SUPPORT_LINUX /* additional dummy */ + .word 0, 0 + .byte 0, 0x00, 0x00, 0 +#endif + + /* kernel code segment */ + .globl flatcodeseg +flatcodeseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9f, 0xcf, 0 + + /* kernel data segment */ + .globl flatdataseg +flatdataseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x93, 0xcf, 0 + + /* boot code segment, base will be patched */ +bootcodeseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9e, 0x40, 0 + + /* boot data segment, base will be patched */ +bootdataseg = . - gdt +#ifdef HEAP_BELOW_64K + .word 0xffff, 0 + .byte 0, 0x92, 0x00, 0 +#else + .word 0xffff, 0 + .byte 0, 0x92, 0x4f, 0 +#endif + + /* 16 bit real mode, base will be patched */ +bootrealseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9e, 0x00, 0 + + /* limits (etc) for data segment in real mode */ +bootrealdata = . - gdt + .word 0xffff, 0 + .byte 0, 0x92, 0x00, 0 +gdtlen = . - gdt + +#ifdef __ELF__ + .align 16 +#else + .align 4 +#endif +gdtarg: + .word gdtlen-1 /* limit */ + .long 0 /* addr, will be inserted */ + + .text +ENTRY(start) + .code16 + + # Check we are in real mode + movl %cr0, %eax + testl $CR0_PE, %eax + jz 2f + mov $1f, %si + call message + ret +1: .asciz "must be in real mode\r\n" +2: + + xorl %eax, %eax + mov %cs, %ax + mov %ax, %ds + mov %ax, %es + movl %eax, _C_LABEL(ourseg) +#ifdef STACK_START + add $STACK_START / 16, %ax + mov %ax, %ss + mov $0xfffc, %sp +#endif + + /* fix up GDT entries for bootstrap */ +#define FIXUP(gdt_index) \ + movw %ax, gdt+gdt_index+2; \ + movb %bl, gdt+gdt_index+4 + + mov %cs, %ax + shll $4, %eax + shldl $16, %eax, %ebx + FIXUP(bootcodeseg) + FIXUP(bootrealseg) + FIXUP(bootdataseg) + + /* fix up GDT pointer */ + addl $gdt, %eax + movl %eax, gdtarg+2 + + /* change to protected mode */ + calll _C_LABEL(real_to_prot) + .code32 + + /* clear the bss */ + movl $_C_LABEL(edata), %edi + movl $_C_LABEL(end), %ecx + subl %edi, %ecx + xorb %al, %al + rep + stosb + + call _C_LABEL(doscommain) +ENTRY(_rtt) + call _C_LABEL(prot_to_real) + .code16 +ENTRY(exit16) + sti + movb $0x4c, %ah /* return */ + int $0x21 + +/* + * real_to_prot() + * transfer from real mode to protected mode. + */ +ENTRY(real_to_prot) + .code16 + pushl %eax + # guarantee that interrupt is disabled when in prot mode + cli + + # load the gdtr + lgdtl %cs:gdtarg + + # set the PE bit of CR0 + movl %cr0, %eax + orl $CR0_PE, %eax + movl %eax, %cr0 + + # make intrasegment jump to flush the processor pipeline and + # reload CS register + ljmp $bootcodeseg, $xprot + +xprot: + .code32 + # we are in USE32 mode now + # set up the protected mode segment registers : DS, SS, ES + movl $bootdataseg, %eax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss +#ifdef STACK_START + addl $STACK_START, %esp +#endif + + popl %eax + ret + +/* + * prot_to_real() + * transfer from protected mode to real mode + */ +ENTRY(prot_to_real) + .code32 + pushl %eax + # set up a dummy stack frame for the second seg change. + # Adjust the intersegment jump instruction following + # the clearing of protected mode bit. + # This is self-modifying code, but we need a writable + # code segment, and an intersegment return does not give us that. + + movl _C_LABEL(ourseg), %eax + movw %ax, xreal-2 + + /* + * Load the segment registers while still in protected mode. + * Otherwise the control bits don't get changed. + * The correct values are loaded later. + */ + movw $bootrealdata, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + + # Change to use16 mode. + ljmp $bootrealseg, $x16 + +x16: + .code16 + # clear the PE bit of CR0 + movl %cr0, %eax + andl $~CR0_PE, %eax + movl %eax, %cr0 + + # Here we have an 16 bits intersegment jump. + ljmp $0, $xreal /* segment patched above */ + +xreal: + # we are in real mode now + # set up the real mode segment registers : DS, SS, ES + mov %cs, %ax + mov %ax, %ds + mov %ax, %es +#ifdef STACK_START + add $STACK_START / 16, %ax + mov %ax, %ss + subl $STACK_START, %esp +#else + mov %ax, %ss +#endif + push %bp + movw %sp, %bp + /* check we are returning to an address below 64k */ + movw 2/*bp*/ + 4/*eax*/ + 2(%bp), %ax /* high bits ret addr */ + test %ax, %ax + jne 1f + pop %bp + + sti + popl %eax + retl + +1: movw $2f, %si + call message + movl 2/*bp*/ + 4/*eax*/(%bp), %eax /* return address */ + call dump_eax + jmp exit16 +2: .asciz "prot_to_real can't return to " + + +/************************************************************************** +___MAIN - Dummy to keep GCC happy +**************************************************************************/ +ENTRY(__main) + ret + +/* + * pbzero(dst, cnt) + * where dst is a physical address and cnt is the length + */ +ENTRY(pbzero) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %es + pushl %edi + + cld + + # set %es to point at the flat segment + movl $flatdataseg, %eax + mov %ax, %es + + movl 8(%ebp), %edi # destination + movl 12(%ebp), %ecx # count + xorl %eax, %eax # value + + rep + stosb + + popl %edi + popl %es + popl %ebp + ret + +/* + * vpbcopy(src, dst, cnt) + * where src is a virtual address and dst is a physical address + */ +ENTRY(vpbcopy) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %es + pushl %esi + pushl %edi + + cld + + # set %es to point at the flat segment + movl $flatdataseg, %eax + mov %ax, %es + + movl 8(%ebp), %esi # source + movl 12(%ebp), %edi # destination + movl 16(%ebp), %ecx # count + + rep + movsb + + popl %edi + popl %esi + popl %es + popl %ebp + ret + +/* + * pvbcopy(src, dst, cnt) + * where src is a physical address and dst is a virtual address + */ +ENTRY(pvbcopy) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ds + pushl %esi + pushl %edi + + cld + + # set %ds to point at the flat segment + movl $flatdataseg, %eax + mov %ax, %ds + + movl 8(%ebp), %esi # source + movl 12(%ebp), %edi # destination + movl 16(%ebp), %ecx # count + + rep + movsb + + popl %edi + popl %esi + popl %ds + popl %ebp + ret + +ENTRY(vtophys) + .code32 + movl _C_LABEL(ourseg), %eax + shll $4, %eax + addl 4(%esp), %eax + ret + +message: + .code16 + pushal +message_1: + cld +1: lodsb + testb %al, %al + jz 2f + movb $0xe, %ah + movw $1, %bx + int $0x10 + jmp 1b + +2: movb $0x86, %ah + mov $16, %cx + int $0x15 /* delay about a second */ + popal + ret + +/* These are useful for debugging + */ + .data +eax_buf: + .long 0, 0, 0, 0 + .text +ENTRY(dump_eax) + .code16 + pushal + movw $eax_buf, %si + mov %si, %di + movw $8, %cx +1: roll $4, %eax + mov %ax, %bx + andb $0x0f, %al + addb $0x30, %al /* 30..3f - clear AF */ +#if 1 /* 5 bytes to generate real hex... */ + daa /* 30..39, 40..45 */ + addb $0xc0, %al /* f0..f9, 00..05 */ + adcb $0x40, %al /* 30..39, 41..45 */ +#endif + movb %al, (%di) /* %es != %ds, so can't ... */ + inc %di /* ... use stosb */ + mov %bx, %ax + loop 1b + movw $0x20, %ax /* space + null */ + movw %ax, (%di) + jmp message_1 + + .globl _C_LABEL(trace_word) +_C_LABEL(trace_word): + .code32 + movl 4(%esp), %edx + + call _C_LABEL(prot_to_real) + .code16 + movl %edx, %eax + call dump_eax + calll _C_LABEL(real_to_prot) + .code32 + ret + + .globl _C_LABEL(trace_str) +_C_LABEL(trace_str): + .code32 + pushl %esi + + call _C_LABEL(prot_to_real) + .code16 + mov %sp, %si + mov 8(%si), %si + call message + calll _C_LABEL(real_to_prot) + .code32 + popl %esi + ret + +#ifdef XMS + +/* pointer to XMS driver, 0 if no XMS used */ + + .data +_C_LABEL(xmsdrv): + .long 0 + + .text +ENTRY(checkxms) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %edx + pushl %es + pushl %esi + pushl %edi + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movw $0x4300, %ax + int $0x2f /* check if XMS installed */ + cmpb $0x80, %al + jnz noxms + + movw $0x4310, %ax + int $0x2f /* get driver address */ + + movw %bx, _C_LABEL(xmsdrv) /* save es:bx to _xmsdrv */ + movw %es, _C_LABEL(xmsdrv) + 2 + + movb $0x08, %ah /* XMS: query free extended memory */ +#if 0 + movb $0x00, %bl +#endif + lcall *_C_LABEL(xmsdrv) + jmp xdone + +noxms: /* no XMS manager found */ + mov $0, %dx + +xdone: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + xorl %eax, %eax + movw %dx, %ax + + popl %edi + popl %esi + popl %es + popl %edx + popl %ebx + popl %ebp + ret + +/* + Allocate a block of XMS memory with the requested size + void *xmsalloc(long int kBytes); + + Depends on _xmsdrv being set by getextmem() before first call + to this function. + + Return value: a physical address. +*/ +ENTRY(xmsalloc) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %edx + pushl %esi + pushl %edi + + movl 0x8(%ebp), %edx # Kbytes needed + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x09, %ah # XMS allocate block + lcall *_C_LABEL(xmsdrv) # result: handle in %dx + movb $0x0c, %ah # XMS lock block + lcall *_C_LABEL(xmsdrv) # result: 32 bit physical addr in DX:BX + + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %edx, %eax + shl $16, %eax + movw %bx, %ax # result in %eax + + popl %edi + popl %esi + popl %edx + popl %ebx + popl %ebp + ret + +/* + * ppbcopy(src, dst, cnt) + * where src and dst are physical addresses + */ +ENTRY(ppbcopy) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %es + pushl %esi + pushl %edi + + cld + + # set %es to point at the flat segment + movl $flatdataseg, %eax + mov %ax, %es + + movl 8(%ebp), %esi # source + movl 12(%ebp), %edi # destination + movl 16(%ebp), %ecx # count + + es + rep + movsb + + popl %edi + popl %esi + popl %es + popl %ebp + ret + +#endif diff --git a/sys/arch/i386/stand/lib/diskbuf.c b/sys/arch/i386/stand/lib/diskbuf.c new file mode 100644 index 000000000..645cf7579 --- /dev/null +++ b/sys/arch/i386/stand/lib/diskbuf.c @@ -0,0 +1,57 @@ +/* $NetBSD: diskbuf.c,v 1.6 2005/12/11 12:17:48 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* data buffer for BIOS disk / DOS I/O */ + +#include +#include "diskbuf.h" + +char *diskbufp; /* allocated from heap */ + +const void *diskbuf_user; + +/* + * Global shared "diskbuf" is used as read ahead buffer. + * This MAY have to not cross a 64k boundary. + * In practise it is allocated out of the heap early on... + * NB a statically allocated diskbuf is not guaranteed to not + * cross a 64k boundary. + */ +char * +alloc_diskbuf(const void *user) +{ + diskbuf_user = user; + if (!diskbufp) { + diskbufp = alloc(DISKBUFSIZE); + if (((int)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) { + printf("diskbufp %x\n", (unsigned)diskbufp); + panic("diskbuf crosses 64k boundary"); + } + } + return diskbufp; +} diff --git a/sys/arch/i386/stand/lib/diskbuf.h b/sys/arch/i386/stand/lib/diskbuf.h new file mode 100644 index 000000000..a4b9feac3 --- /dev/null +++ b/sys/arch/i386/stand/lib/diskbuf.h @@ -0,0 +1,40 @@ +/* $NetBSD: diskbuf.h,v 1.4 2005/12/11 12:17:48 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* data buffer for BIOS disk / DOS I/O */ + +#ifndef DISKBUFSIZE +/* Read ahead buffer large enough for one track on a 1440K floppy. + */ +#define DISKBUFSIZE (18*512) +#endif + +extern char *diskbufp; /* allocated from heap... */ +extern const void *diskbuf_user; /* using function sets it to unique + value to allow check if overwritten*/ +char *alloc_diskbuf(const void *); diff --git a/sys/arch/i386/stand/lib/dos_file.S b/sys/arch/i386/stand/lib/dos_file.S new file mode 100644 index 000000000..1c5547d65 --- /dev/null +++ b/sys/arch/i386/stand/lib/dos_file.S @@ -0,0 +1,203 @@ +/* $NetBSD: dos_file.S,v 1.6 2009/11/21 11:52:57 dsl Exp $ */ + +/* extracted from Tor Egge's patches for NetBSD boot */ + +#include + +/* +# MSDOS call "INT 0x21 Function 0x3d" to open a file. +# Call with %ah = 0x3d +# %al = 0x0 (access and sharing modes) +# %ds:%dx = ASCIZ filename +# %cl = attribute mask of files to look for +*/ + + .globl _C_LABEL(doserrno) +_C_LABEL(doserrno): .long 1 + +ENTRY(dosopen) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %edx + pushl %ebx + pushl %esi + pushl %edi + + movl 0x8(%ebp), %edx # File name. + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %ds + movl %edx, %eax + shrl $4, %eax + mov %ds, %si + add %si, %ax + mov %ax, %ds + and $0xf, %dx + + movb $0x3d, %ah # Open existing file. + movb $0x0 , %al # ro + + sti + int $0x21 + cli + pop %ds + + jnc ok1 + mov %ax, _C_LABEL(doserrno) + movl $-1, %edx + jmp err1 +ok1: + movl $0,%edx + mov %ax, %dx +err1: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %edx, %eax # return value in %eax + + popl %edi + popl %esi + popl %ebx + popl %edx + popl %ebp + ret + +ENTRY(dosread) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + movl 0x8(%ebp), %ebx # File handle + movl 0xc(%ebp), %edx # Buffer. + movl 0x10(%ebp), %ecx # Bytes to read + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + push %ds + movl %edx, %eax + shrl $4, %eax + mov %ds, %si + add %si, %ax + mov %ax, %ds + and $0xf, %dx + + movb $0x3f, %ah # Read from file or device + + sti + int $0x21 + cli + pop %ds + + jnc ok2 + mov %ax, _C_LABEL(doserrno) + movl $-1, %edx + jmp err2 +ok2: + movl $0,%edx + mov %ax, %dx +err2: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %edx, %eax # return value in %eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +ENTRY(dosclose) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %esi + pushl %edi + + movl 0x8(%ebp), %ebx # File handle + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x3e, %ah # Close file. + + sti + int $0x21 + cli + + jnc ok3 + mov %ax, _C_LABEL(doserrno) + movl $-1, %ebx + jmp err3 +ok3: + movl $0, %ebx +err3: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %ebx, %eax # return value in %eax + + popl %edi + popl %esi + popl %ebx + popl %ebp + ret + +ENTRY(dosseek) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %esi + pushl %edi + + movl 0x8(%ebp), %ebx # File handle + movl 0xc(%ebp), %ecx # Offset + movl 0x10(%ebp) , %edx # whence + + call _C_LABEL(prot_to_real) # enter real mode + .code16 + + movb $0x42, %ah # Seek + movb %dl, %al # whence + mov %cx, %dx #offs lo + shrl $0x10, %ecx #offs hi + + sti + int $0x21 + cli + + jnc ok4 + mov %ax, _C_LABEL(doserrno) + movl $-1, %edx + jmp err4 +ok4: + shll $0x10, %edx #new ofs hi + mov %ax, %dx #new ofs lo +err4: + calll _C_LABEL(real_to_prot) # back to protected mode + .code32 + + movl %edx, %eax # return value in %eax + + popl %edi + popl %esi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret diff --git a/sys/arch/i386/stand/lib/dosfile.c b/sys/arch/i386/stand/lib/dosfile.c new file mode 100644 index 000000000..e2ab313e4 --- /dev/null +++ b/sys/arch/i386/stand/lib/dosfile.c @@ -0,0 +1,240 @@ +/* $NetBSD: dosfile.c,v 1.15 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * DOS filesystem for libsa + * standalone - uses no device, works only with DOS running + * needs lowlevel parts from dos_file.S + */ + +#include + +#include "diskbuf.h" +#include "dosfile.h" + +extern int dosopen(const char *); +extern void dosclose(int); +extern int dosread(int, char *, int); +extern int dosseek(int, int, int); + +struct dosfile { + int doshandle, off; +}; + +extern int doserrno; /* in dos_file.S */ + +static int dos2errno(void); + +static int +dos2errno(void) +{ + int err; + + switch (doserrno) { + case 1: + case 4: + case 12: + default: + err = EIO; + case 2: + case 3: + err = ENOENT; + case 5: + err = EPERM; + case 6: + err = EINVAL; + } + return err; +} + +__compactcall int +dos_open(const char *path, struct open_file *f) +{ + struct dosfile *df; + + df = (struct dosfile *) alloc(sizeof(*df)); + if (!df) + return -1; + + df->off = 0; + df->doshandle = dosopen(path); + if (df->doshandle < 0) { +#ifdef DEBUG + printf("DOS error %d\n", doserrno); +#endif + dealloc(df, sizeof(*df)); + return dos2errno(); + } + f->f_fsdata = (void *) df; + return 0; +} + +__compactcall int +dos_read(struct open_file *f, void *addr, size_t size, size_t *resid) +{ + struct dosfile *df; + int got; + static int tc = 0; + + df = (struct dosfile *) f->f_fsdata; + + if (!(tc++ % 4)) + twiddle(); + + if ((unsigned long) addr >= 0x10000) { + u_int lsize = size; + + while (lsize > 0) { + u_int tsize; + size_t tgot; + char *p = addr; + + tsize = lsize; + + if (tsize > DISKBUFSIZE) + tsize = DISKBUFSIZE; + + alloc_diskbuf(dos_read); + + tgot = dosread(df->doshandle, diskbufp, tsize); + if (tgot < 0) { +#ifdef DEBUG + printf("DOS error %d\n", doserrno); +#endif + return dos2errno(); + } + memcpy(p, diskbufp, tgot); + + p += tgot; + lsize -= tgot; + + if (tgot != tsize) + break; /* EOF */ + } + got = size - lsize; + } else { + got = dosread(df->doshandle, addr, size); + + if (got < 0) { +#ifdef DEBUG + printf("DOS error %d\n", doserrno); +#endif + return dos2errno(); + } + } + + df->off += got; + size -= got; + + if (resid) + *resid = size; + return 0; +} + +__compactcall int +dos_close(struct open_file *f) +{ + struct dosfile *df; + df = (struct dosfile *) f->f_fsdata; + + dosclose(df->doshandle); + + if (df) + dealloc(df, sizeof(*df)); + return 0; +} + +__compactcall int +dos_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + return EROFS; +} + +__compactcall int +dos_stat(struct open_file *f, struct stat *sb) +{ + struct dosfile *df; + df = (struct dosfile *) f->f_fsdata; + + sb->st_mode = 0444; + sb->st_nlink = 1; + sb->st_uid = 0; + sb->st_gid = 0; + sb->st_size = -1; + return 0; +} + +__compactcall off_t +dos_seek(struct open_file *f, off_t offset, int where) +{ + struct dosfile *df; + int doswhence, res; +#ifdef DOS_CHECK + int checkoffs; +#endif + df = (struct dosfile *) f->f_fsdata; + + switch (where) { + case SEEK_SET: + doswhence = 0; +#ifdef DOS_CHECK + checkoffs = offset; /* don't trust DOS */ +#endif + break; + case SEEK_CUR: + doswhence = 1; +#ifdef DOS_CHECK + checkoffs = df->off + offset; +#endif + break; + case SEEK_END: + doswhence = 2; +#ifdef DOS_CHECK + checkoffs = -1; /* we dont know len */ +#endif + break; + default: + errno = EOFFSET; + return -1; + } + res = dosseek(df->doshandle, offset, doswhence); + if (res == -1) { + errno = dos2errno(); + return -1; + } +#ifdef DOS_CHECK + if ((checkoffs != -1) && (res != checkoffs)) { + printf("dosfile: unexpected seek result (%d+%d(%d)=%d)\n", + df->off, offset, where, res); + errno = EOFFSET; + return -1; + } +#endif + df->off = res; + return res; +} diff --git a/sys/arch/i386/stand/lib/dosfile.h b/sys/arch/i386/stand/lib/dosfile.h new file mode 100644 index 000000000..ccffbd042 --- /dev/null +++ b/sys/arch/i386/stand/lib/dosfile.h @@ -0,0 +1,29 @@ +/* $NetBSD: dosfile.h,v 1.4 2005/12/11 12:17:48 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +FS_DEF(dos); diff --git a/sys/arch/i386/stand/lib/dump_eax.S b/sys/arch/i386/stand/lib/dump_eax.S new file mode 100644 index 000000000..f2d646cf2 --- /dev/null +++ b/sys/arch/i386/stand/lib/dump_eax.S @@ -0,0 +1,59 @@ +/* $NetBSD: dump_eax.S,v 1.4 2009/11/19 22:08:14 dsl Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* This is useful for debugging - although you may need to + * delete some code to fit it in. + * %ds:dump_eax_buff must be somewhere it is safe to write 10 bytes. + */ + +ENTRY(dump_eax) + .code16 + pusha /* saves bottom 16 bits only! */ + movw $dump_eax_buff, %si + mov %si, %di + movw $8, %cx +1: roll $4, %eax + push %ax + andb $0x0f, %al + addb $0x30, %al /* 30..3f - clear AF */ +#if 1 /* 5 bytes to generate real hex... */ + daa /* 30..39, 40..45 */ + addb $0xc0, %al /* f0..f9, 00..05 */ + adcb $0x40, %al /* 30..39, 41..46 */ +#endif + mov %al,(%di) + inc %di + pop %ax + loop 1b + movw $0x20,(%di) /* space + NIL */ + jmp message_1 diff --git a/sys/arch/i386/stand/lib/exec.c b/sys/arch/i386/stand/lib/exec.c new file mode 100644 index 000000000..45abbe187 --- /dev/null +++ b/sys/arch/i386/stand/lib/exec.c @@ -0,0 +1,743 @@ +/* $NetBSD: exec.c,v 1.49 2011/11/28 07:56:54 tls Exp $ */ + +/*- + * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +/* + * starts NetBSD a.out kernel + * needs lowlevel startup from startprog.S + * This is a special version of exec.c to support use of XMS. + */ + +#include +#include +#include + +#include + +#include +#include + +#include "loadfile.h" +#include "libi386.h" +#include "bootinfo.h" +#include "bootmod.h" +#include "vbe.h" +#ifdef SUPPORT_PS2 +#include "biosmca.h" +#endif + +#define BOOT_NARGS 6 + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define MODULE_WARNING_SEC 5 + +extern struct btinfo_console btinfo_console; + +boot_module_t *boot_modules; +bool boot_modules_enabled = true; +bool kernel_loaded; + +typedef struct userconf_command { + char *uc_text; + size_t uc_len; + struct userconf_command *uc_next; +} userconf_command_t; +userconf_command_t *userconf_commands = NULL; + +static struct btinfo_framebuffer btinfo_framebuffer; + +static struct btinfo_modulelist *btinfo_modulelist; +static size_t btinfo_modulelist_size; +static uint32_t image_end; +static char module_base[64] = "/"; +static int howto; + +static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL; +static size_t btinfo_userconfcommands_size = 0; + +static void module_init(const char *); +static void module_add_common(char *, uint8_t); + +static void userconf_init(void); + +void +framebuffer_configure(struct btinfo_framebuffer *fb) +{ + if (fb) + btinfo_framebuffer = *fb; + else { + btinfo_framebuffer.physaddr = 0; + btinfo_framebuffer.flags = 0; + } +} + +void +module_add(char *name) +{ + return module_add_common(name, BM_TYPE_KMOD); +} + +void +splash_add(char *name) +{ + return module_add_common(name, BM_TYPE_IMAGE); +} + +void +rnd_add(char *name) +{ + return module_add_common(name, BM_TYPE_RND); +} + +static void +module_add_common(char *name, uint8_t type) +{ + boot_module_t *bm, *bmp; + size_t len; + char *str; + + while (*name == ' ' || *name == '\t') + ++name; + + bm = alloc(sizeof(boot_module_t)); + len = strlen(name) + 1; + str = alloc(len); + if (bm == NULL || str == NULL) { + printf("couldn't allocate module\n"); + return; + } + memcpy(str, name, len); + bm->bm_path = str; + bm->bm_next = NULL; + bm->bm_type = type; + if (boot_modules == NULL) + boot_modules = bm; + else { + for (bmp = boot_modules; bmp->bm_next; + bmp = bmp->bm_next) + ; + bmp->bm_next = bm; + } +} + +void +userconf_add(char *cmd) +{ + userconf_command_t *uc; + size_t len; + char *text; + + while (*cmd == ' ' || *cmd == '\t') + ++cmd; + + uc = alloc(sizeof(*uc)); + if (uc == NULL) { + printf("couldn't allocate command\n"); + return; + } + + len = strlen(cmd) + 1; + text = alloc(len); + if (text == NULL) { + dealloc(uc, sizeof(*uc)); + printf("couldn't allocate command\n"); + return; + } + memcpy(text, cmd, len); + + uc->uc_text = text; + uc->uc_len = len; + uc->uc_next = NULL; + + if (userconf_commands == NULL) + userconf_commands = uc; + else { + userconf_command_t *ucp; + for (ucp = userconf_commands; ucp->uc_next != NULL; + ucp = ucp->uc_next) + ; + ucp->uc_next = uc; + } +} + +static int +common_load_kernel(const char *file, u_long *basemem, u_long *extmem, + physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX]) +{ + int fd; +#ifdef XMS + u_long xmsmem; + physaddr_t origaddr = loadaddr; +#endif + + *extmem = getextmem(); + *basemem = getbasemem(); + +#ifdef XMS + if ((getextmem1() == 0) && (xmsmem = checkxms())) { + u_long kernsize; + + /* + * With "CONSERVATIVE_MEMDETECT", extmem is 0 because + * getextmem() is getextmem1(). Without, the "smart" + * methods could fail to report all memory as well. + * xmsmem is a few kB less than the actual size, but + * better than nothing. + */ + if (xmsmem > *extmem) + *extmem = xmsmem; + /* + * Get the size of the kernel + */ + marks[MARK_START] = loadaddr; + if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1) + return EIO; + close(fd); + + kernsize = marks[MARK_END]; + kernsize = (kernsize + 1023) / 1024; + + loadaddr = xmsalloc(kernsize); + if (!loadaddr) + return ENOMEM; + } +#endif + marks[MARK_START] = loadaddr; + if ((fd = loadfile(file, marks, + LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1) + return EIO; + + close(fd); + + /* Now we know the root fs type, load modules for it. */ + module_add(fsmod); + if (fsmod2 != NULL && strcmp(fsmod, fsmod2) != 0) + module_add(fsmod2); + + /* + * Gather some information for the kernel. Do this after the + * "point of no return" to avoid memory leaks. + * (but before DOS might be trashed in the XMS case) + */ +#ifdef PASS_BIOSGEOM + bi_getbiosgeom(); +#endif +#ifdef PASS_MEMMAP + bi_getmemmap(); +#endif + +#ifdef XMS + if (loadaddr != origaddr) { + /* + * We now have done our last DOS IO, so we may + * trash the OS. Copy the data from the temporary + * buffer to its real address. + */ + marks[MARK_START] -= loadaddr; + marks[MARK_END] -= loadaddr; + marks[MARK_SYM] -= loadaddr; + marks[MARK_END] -= loadaddr; + ppbcopy(loadaddr, origaddr, marks[MARK_END]); + } +#endif + marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & + (-sizeof(int)); + image_end = marks[MARK_END]; + kernel_loaded = true; + + return 0; +} + +int +exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy, + void (*callback)(void)) +{ + u_long boot_argv[BOOT_NARGS]; + u_long marks[MARK_MAX]; + struct btinfo_symtab btinfo_symtab; + u_long extmem; + u_long basemem; + +#ifdef DEBUG + printf("exec: file=%s loadaddr=0x%lx\n", + file ? file : "NULL", loadaddr); +#endif + + BI_ALLOC(32); /* ??? */ + + BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console)); + + howto = boothowto; + + if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks)) + goto out; + + boot_argv[0] = boothowto; + boot_argv[1] = 0; + boot_argv[2] = vtophys(bootinfo); /* old cyl offset */ + boot_argv[3] = marks[MARK_END]; + boot_argv[4] = extmem; + boot_argv[5] = basemem; + + /* pull in any modules if necessary */ + if (boot_modules_enabled) { + module_init(file); + if (btinfo_modulelist) { + BI_ADD(btinfo_modulelist, BTINFO_MODULELIST, + btinfo_modulelist_size); + } + } + + userconf_init(); + if (btinfo_userconfcommands != NULL) + BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS, + btinfo_userconfcommands_size); + +#ifdef DEBUG + printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], + marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); +#endif + + btinfo_symtab.nsym = marks[MARK_NSYM]; + btinfo_symtab.ssym = marks[MARK_SYM]; + btinfo_symtab.esym = marks[MARK_END]; + BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab)); + + /* set new video mode if necessary */ + vbe_commit(); + BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER, + sizeof(struct btinfo_framebuffer)); + + if (callback != NULL) + (*callback)(); + startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv, + x86_trunc_page(basemem*1024)); + panic("exec returned"); + +out: + BI_FREE(); + bootinfo = 0; + return -1; +} + +static void +extract_device(const char *path, char *buf, size_t buflen) +{ + int i; + + if (strchr(path, ':') != NULL) { + for (i = 0; i < buflen - 2 && path[i] != ':'; i++) + buf[i] = path[i]; + buf[i++] = ':'; + buf[i] = '\0'; + } else + buf[0] = '\0'; +} + +static const char * +module_path(boot_module_t *bm, const char *kdev) +{ + static char buf[256]; + char name_buf[256], dev_buf[64]; + const char *name, *name2, *p; + + name = bm->bm_path; + for (name2 = name; *name2; ++name2) { + if (*name2 == ' ' || *name2 == '\t') { + strlcpy(name_buf, name, sizeof(name_buf)); + if (name2 - name < sizeof(name_buf)) + name_buf[name2 - name] = '\0'; + name = name_buf; + break; + } + } + if ((p = strchr(name, ':')) != NULL) { + /* device specified, use it */ + if (p[1] == '/') + snprintf(buf, sizeof(buf), "%s", name); + else { + p++; + extract_device(name, dev_buf, sizeof(dev_buf)); + snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", + dev_buf, module_base, p, p); + } + } else { + /* device not specified; load from kernel device if known */ + if (name[0] == '/') + snprintf(buf, sizeof(buf), "%s%s", kdev, name); + else + snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", + kdev, module_base, name, name); + } + + return buf; +} + +static int +module_open(boot_module_t *bm, int mode, const char *kdev, bool doload) +{ + int fd; + const char *path; + + /* check the expanded path first */ + path = module_path(bm, kdev); + fd = open(path, mode); + if (fd != -1) { + if ((howto & AB_SILENT) == 0 && doload) + printf("Loading %s ", path); + } else { + /* now attempt the raw path provided */ + fd = open(bm->bm_path, mode); + if (fd != -1 && (howto & AB_SILENT) == 0 && doload) + printf("Loading %s ", bm->bm_path); + } + if (!doload && fd == -1) { + printf("WARNING: couldn't open %s", bm->bm_path); + if (strcmp(bm->bm_path, path) != 0) + printf(" (%s)", path); + printf("\n"); + } + return fd; +} + +static void +module_init(const char *kernel_path) +{ + struct bi_modulelist_entry *bi; + struct stat st; + const char *machine; + char kdev[64]; + char *buf; + boot_module_t *bm; + size_t len; + off_t off; + int err, fd, nfail = 0; + + extract_device(kernel_path, kdev, sizeof(kdev)); + + switch (netbsd_elf_class) { + case ELFCLASS32: + machine = "i386"; + break; + case ELFCLASS64: + machine = "amd64"; + break; + default: + machine = "generic"; + break; + } + if (netbsd_version / 1000000 % 100 == 99) { + /* -current */ + snprintf(module_base, sizeof(module_base), + "/stand/%s/%d.%d.%d/modules", machine, + netbsd_version / 100000000, + netbsd_version / 1000000 % 100, + netbsd_version / 100 % 100); + } else if (netbsd_version != 0) { + /* release */ + snprintf(module_base, sizeof(module_base), + "/stand/%s/%d.%d/modules", machine, + netbsd_version / 100000000, + netbsd_version / 1000000 % 100); + } + + /* First, see which modules are valid and calculate btinfo size */ + len = sizeof(struct btinfo_modulelist); + for (bm = boot_modules; bm; bm = bm->bm_next) { + fd = module_open(bm, 0, kdev, false); + if (fd == -1) { + bm->bm_len = -1; + ++nfail; + continue; + } + err = fstat(fd, &st); + if (err == -1 || st.st_size == -1) { + printf("WARNING: couldn't stat %s\n", bm->bm_path); + close(fd); + bm->bm_len = -1; + ++nfail; + continue; + } + bm->bm_len = st.st_size; + close(fd); + len += sizeof(struct bi_modulelist_entry); + } + + /* Allocate the module list */ + btinfo_modulelist = alloc(len); + if (btinfo_modulelist == NULL) { + printf("WARNING: couldn't allocate module list\n"); + wait_sec(MODULE_WARNING_SEC); + return; + } + memset(btinfo_modulelist, 0, len); + btinfo_modulelist_size = len; + + /* Fill in btinfo structure */ + buf = (char *)btinfo_modulelist; + btinfo_modulelist->num = 0; + off = sizeof(struct btinfo_modulelist); + + for (bm = boot_modules; bm; bm = bm->bm_next) { + if (bm->bm_len == -1) + continue; + fd = module_open(bm, 0, kdev, true); + if (fd == -1) + continue; + image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + len = pread(fd, (void *)image_end, SSIZE_MAX); + if (len < bm->bm_len) { + if ((howto & AB_SILENT) != 0) + printf("Loading %s ", bm->bm_path); + printf(" FAILED\n"); + } else { + btinfo_modulelist->num++; + bi = (struct bi_modulelist_entry *)(buf + off); + off += sizeof(struct bi_modulelist_entry); + strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1); + bi->base = image_end; + bi->len = len; + switch (bm->bm_type) { + case BM_TYPE_KMOD: + bi->type = BI_MODULE_ELF; + break; + case BM_TYPE_IMAGE: + bi->type = BI_MODULE_IMAGE; + break; + case BM_TYPE_RND: + default: + /* safest -- rnd checks the sha1 */ + bi->type = BI_MODULE_RND; + break; + } + if ((howto & AB_SILENT) == 0) + printf(" \n"); + } + if (len > 0) + image_end += len; + close(fd); + } + btinfo_modulelist->endpa = image_end; + + if (nfail > 0) { + printf("WARNING: %d module%s failed to load\n", + nfail, nfail == 1 ? "" : "s"); +#if notyet + wait_sec(MODULE_WARNING_SEC); +#endif + } +} + +static void +userconf_init(void) +{ + size_t count, len; + userconf_command_t *uc; + char *buf; + off_t off; + + /* Calculate the userconf commands list size */ + count = 0; + for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) + count++; + len = sizeof(btinfo_userconfcommands) + + count * sizeof(struct bi_userconfcommand); + + /* Allocate the userconf commands list */ + btinfo_userconfcommands = alloc(len); + if (btinfo_userconfcommands == NULL) { + printf("WARNING: couldn't allocate userconf commands list\n"); + return; + } + memset(btinfo_userconfcommands, 0, len); + btinfo_userconfcommands_size = len; + + /* Fill in btinfo structure */ + buf = (char *)btinfo_userconfcommands; + off = sizeof(*btinfo_userconfcommands); + btinfo_userconfcommands->num = 0; + for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) { + struct bi_userconfcommand *bi; + bi = (struct bi_userconfcommand *)(buf + off); + strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1); + + off += sizeof(*bi); + btinfo_userconfcommands->num++; + } +} + +int +exec_multiboot(const char *file, char *args) +{ + struct multiboot_info *mbi; + struct multiboot_module *mbm; + struct bi_modulelist_entry *bim; + int i, len; + u_long marks[MARK_MAX]; + u_long extmem; + u_long basemem; + char *cmdline; + + mbi = alloc(sizeof(struct multiboot_info)); + mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; + + if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks)) + goto out; + + mbi->mi_mem_upper = extmem; + mbi->mi_mem_lower = basemem; + + if (args) { + mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE; + len = strlen(file) + 1 + strlen(args) + 1; + cmdline = alloc(len); + snprintf(cmdline, len, "%s %s", file, args); + mbi->mi_cmdline = (char *) vtophys(cmdline); + } + + /* pull in any modules if necessary */ + if (boot_modules_enabled) { + module_init(file); + if (btinfo_modulelist) { + mbm = alloc(sizeof(struct multiboot_module) * + btinfo_modulelist->num); + + bim = (struct bi_modulelist_entry *) + (((char *) btinfo_modulelist) + + sizeof(struct btinfo_modulelist)); + for (i = 0; i < btinfo_modulelist->num; i++) { + mbm[i].mmo_start = bim->base; + mbm[i].mmo_end = bim->base + bim->len; + mbm[i].mmo_string = (char *)vtophys(bim->path); + mbm[i].mmo_reserved = 0; + bim++; + } + mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS; + mbi->mi_mods_count = btinfo_modulelist->num; + mbi->mi_mods_addr = vtophys(mbm); + } + } + +#ifdef DEBUG + printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], + marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); +#endif + + +#if 0 + if (btinfo_symtab.nsym) { + mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; + mbi->mi_elfshdr_addr = marks[MARK_SYM]; + btinfo_symtab.nsym = marks[MARK_NSYM]; + btinfo_symtab.ssym = marks[MARK_SYM]; + btinfo_symtab.esym = marks[MARK_END]; +#endif + + multiboot(marks[MARK_ENTRY], vtophys(mbi), + x86_trunc_page(mbi->mi_mem_lower*1024)); + panic("exec returned"); + +out: + dealloc(mbi, 0); + return -1; +} + +void +x86_progress(const char *fmt, ...) +{ + va_list ap; + + if ((howto & AB_SILENT) != 0) + return; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} diff --git a/sys/arch/i386/stand/lib/gatea20.c b/sys/arch/i386/stand/lib/gatea20.c new file mode 100644 index 000000000..a5ab0bfb6 --- /dev/null +++ b/sys/arch/i386/stand/lib/gatea20.c @@ -0,0 +1,80 @@ +/* $NetBSD: gatea20.c,v 1.12 2009/08/23 12:31:05 jmcneill Exp $ */ + +/* extracted from freebsd:sys/i386/boot/biosboot/io.c */ + +#include + +#include + +#include "libi386.h" +#include "biosmca.h" +#include "cpufunc.h" + +#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ +#define K_STATUS 0x64 /* keyboard status */ +#define K_CMD 0x64 /* keybd ctlr command (write-only) */ + +#define K_OBUF_FUL 0x01 /* output buffer full */ +#define K_IBUF_FUL 0x02 /* input buffer full */ + +#define KC_CMD_WIN 0xd0 /* read output port */ +#define KC_CMD_WOUT 0xd1 /* write output port */ +#define KB_A20 0x9f /* enable A20, + reset (!), + enable output buffer full interrupt + enable data line + disable clock line */ + +/* + * Gate A20 for high memory + */ +static unsigned char x_20 = KB_A20; + +void +gateA20(void) +{ + int biosA20(void); + u_long psl; + + /* + * First, try asking the BIOS to enable A20. + * + * If that fails, try system configuration port 0x92 but only + * if known to be necessary. Not all systems enable A20 via the + * keyboard controller, some don't have keyboard controllers, + * and playing with port 0x92 may cause some systems to break. + * + * Otherwise, use the traditional method (keyboard controller). + */ + if (!biosA20()) + return; + psl = x86_read_psl(); + x86_disable_intr(); + if ( +#ifdef SUPPORT_PS2 + biosmca_ps2model == 0xf82 || +#endif + (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) { + int data; + + data = inb(0x92); + outb(0x92, data | 0x2); + } else { + while (inb(K_STATUS) & K_IBUF_FUL); + + while (inb(K_STATUS) & K_OBUF_FUL) + (void)inb(K_RDWR); + + outb(K_CMD, KC_CMD_WOUT); + + while (inb(K_STATUS) & K_IBUF_FUL); + + outb(K_RDWR, x_20); + + while (inb(K_STATUS) & K_IBUF_FUL); + + while (inb(K_STATUS) & K_OBUF_FUL) + (void)inb(K_RDWR); + } + x86_write_psl(psl); +} diff --git a/sys/arch/i386/stand/lib/getextmemx.c b/sys/arch/i386/stand/lib/getextmemx.c new file mode 100644 index 000000000..b305d6582 --- /dev/null +++ b/sys/arch/i386/stand/lib/getextmemx.c @@ -0,0 +1,93 @@ +/* $NetBSD: getextmemx.c,v 1.10 2011/06/16 13:27:59 joerg Exp $ */ + +/* + * Copyright (c) 1997, 1999 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Try 2 more fancy BIOS calls to get the size of extended + * memory besides the classical int15/88, take maximum. + * needs lowlevel parts from biosmemx.S and biosmem.S + */ + +#include +#include "libi386.h" + +int +getextmemx(void) +{ + int buf[5], i; + int extmem = getextmem1(); +#ifdef SUPPORT_PS2 + struct { + uint16_t len; + uint32_t dta[8]; + /* pad to 64 bytes - without this, machine would reset */ + uint8_t __pad[30]; + } __packed bufps2; +#endif + +#ifdef DEBUG_MEMSIZE + printf("extmem1: %xk\n", extmem); +#endif + if (!getextmem2(buf)) { +#ifdef DEBUG_MEMSIZE + printf("extmem2: %xk + %xk\n", buf[0], buf[1] * 64); +#endif + if (buf[0] <= 15 * 1024) { + int help = buf[0]; + if (help == 15 * 1024) + help += buf[1] * 64; + if (extmem < help) + extmem = help; + } + } + + i = 0; + do { + if (getmementry(&i, buf)) + break; +#ifdef DEBUG_MEMSIZE + printf("mementry: (%d) %x %x %x %x %x\n", + i, buf[0], buf[1], buf[2], buf[3], buf[4]); +#endif + if ((buf[4] == 1 && buf[0] == 0x100000) + && extmem < buf[2] / 1024) + extmem = buf[2] / 1024; + } while (i); + +#ifdef SUPPORT_PS2 + /* use local memory information from RETURN MEMORY-MAP INFORMATION */ + if (!getextmemps2((void *) &bufps2)) { + int help = bufps2.dta[0]; + if (help == 15 * 1024) + help += bufps2.dta[1]; + if (extmem < help) + extmem = help; + } +#endif + + return extmem; +} diff --git a/sys/arch/i386/stand/lib/getsecs.c b/sys/arch/i386/stand/lib/getsecs.c new file mode 100644 index 000000000..e5c9daa58 --- /dev/null +++ b/sys/arch/i386/stand/lib/getsecs.c @@ -0,0 +1,41 @@ +/* $NetBSD: getsecs.c,v 1.4 2009/01/12 11:32:44 tsutsui Exp $ */ + +/* extracted from netbsd:sys/arch/i386/netboot/misc.c */ + +#include + +#include +#include + +#include "libi386.h" + +static inline u_long bcd2dec(u_long); + +static inline u_long +bcd2dec(u_long arg) +{ + return (arg >> 4) * 10 + (arg & 0x0f); +} + +satime_t +getsecs(void) { + /* + * Return the current time in seconds + */ + + u_long t; + satime_t sec; + + if (biosgetrtc(&t)) + panic("RTC invalid"); + + sec = bcd2dec(t & 0xff); + sec *= 60; + t >>= 8; + sec += bcd2dec(t & 0xff); + sec *= 60; + t >>= 8; + sec += bcd2dec(t & 0xff); + + return sec; +} diff --git a/sys/arch/i386/stand/lib/isadma.c b/sys/arch/i386/stand/lib/isadma.c new file mode 100644 index 000000000..acd47ab41 --- /dev/null +++ b/sys/arch/i386/stand/lib/isadma.c @@ -0,0 +1,43 @@ +/* $NetBSD: isadma.c,v 1.2 2008/12/14 17:03:43 christos Exp $ */ + +/* from: NetBSD:dev/isa/isadma.c */ + +#include +#include + +#include + +#include "isadmavar.h" + +#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */ +#define IO_DMA2 0x0C0 /* 8237A DMA Controller #2 */ +#define DMA37MD_CASCADE 0xc0 /* cascade mode */ +#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ +#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ +#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ +#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ + +/* + * isa_dmacascade(): program 8237 DMA controller channel to accept + * external dma control by a board. + */ +void +isa_dmacascade(int chan) +{ + +#ifdef ISADMA_DEBUG + if (chan < 0 || chan > 7) + panic("isa_dmacascade: impossible request"); +#endif + + /* set dma channel mode, and set dma channel mode */ + if ((chan & 4) == 0) { + outb(DMA1_MODE, chan | DMA37MD_CASCADE); + outb(DMA1_SMSK, chan); + } else { + chan &= 3; + + outb(DMA2_MODE, chan | DMA37MD_CASCADE); + outb(DMA2_SMSK, chan); + } +} diff --git a/sys/arch/i386/stand/lib/isadmavar.h b/sys/arch/i386/stand/lib/isadmavar.h new file mode 100644 index 000000000..f3b91395a --- /dev/null +++ b/sys/arch/i386/stand/lib/isadmavar.h @@ -0,0 +1,3 @@ +/* $NetBSD: isadmavar.h,v 1.2 2008/12/14 17:03:43 christos Exp $ */ + +void isa_dmacascade(int); diff --git a/sys/arch/i386/stand/lib/isapnp.c b/sys/arch/i386/stand/lib/isapnp.c new file mode 100644 index 000000000..cd3ba5f6d --- /dev/null +++ b/sys/arch/i386/stand/lib/isapnp.c @@ -0,0 +1,231 @@ +/* $NetBSD: isapnp.c,v 1.5 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * minimal ISA PnP implementation: find adapter, return settings (1 IO and 1 + * DMA only for now) + */ + +#include +#include + +#include + +#include + +#include "isapnpvar.h" + +#define PNPADDR 0x0279 +#define PNPWDATA 0x0a79 +#define PNPRDATAMIN 0x0203 +#define PNPRDATAMAX 0x03ff + +enum { + DATAPORT, + ISOL, + CONTROL, + WAKE, + RESDATA, + RESSTAT, + SETCSN, + SETLDEV +}; + +#define MEMBASE 0x40 +#define IOBASE 0x60 +#define INTBASE 0x70 +#define DMABASE 0x74 + +static int pnpdataport; + +static int +getiobase(int nr) +{ + unsigned short iobase; + + outb(PNPADDR, SETLDEV); + outb(PNPWDATA, 0); /* subdev 0 */ + + outb(PNPADDR, IOBASE + nr * 2); + iobase = (inb(pnpdataport) << 8); + outb(PNPADDR, IOBASE + nr * 2 + 1); + iobase |= inb(pnpdataport); + + return iobase; +} + +static int +getdmachan(int nr) +{ + unsigned char dmachannel; + + outb(PNPADDR, SETLDEV); + outb(PNPWDATA, 0); /* subdev 0 */ + + outb(PNPADDR, DMABASE + nr); + dmachannel = inb(pnpdataport) & 0x07; + + return dmachannel; +} + +struct cardid { + unsigned char eisaid[4]; + unsigned int serial; + unsigned char crc; +}; + +/* + do isolation, call pnpscanresc() in board config state + */ +static int +pnpisol(int csn) +{ + unsigned char buf[9]; + int i, j; + struct cardid *id; + unsigned char crc = 0x6a; + + /* + * do 72 pairs of reads from ISOL register all but 1 go to sleep + * state (ch. 3.3) + */ + outb(PNPADDR, ISOL); + delay(1000); + + for (i = 0; i < 9; i++) { + for (j = 0; j < 8; j++) { + unsigned char a, b; + int bitset; + + a = inb(pnpdataport); + b = inb(pnpdataport); + if ((a == 0x55) && (b == 0xaa)) + bitset = 1; + else if ((a == 0xff) && (b == 0xff)) + bitset = 0; + else + return -1; /* data port conflict */ + + buf[i] = (buf[i] >> 1) | (bitset << 7); + + if (i < 8) /* calc crc for first 8 bytes (app. + * B.2) */ + crc = (crc >> 1) | + ((bitset != ((crc & 1) == !(crc & 2))) << 7); + + delay(250); + } + } + id = (struct cardid *) buf; + + if (id->crc != crc) + return 0; /* normal end */ + + outb(PNPADDR, SETCSN); + outb(PNPWDATA, csn); /* set csn for winning card and put it to + * config state */ + + return (id->eisaid[0] << 24) | (id->eisaid[1] << 16) + | (id->eisaid[2] << 8) | (id->eisaid[3]); +} + +static void +pnpisolreset(void) +{ + outb(PNPADDR, WAKE); + outb(PNPWDATA, 0); /* put all remaining cards to isolation state */ +} + +/* + send initiation sequence (app. B.1) + */ +static void +pnpinit(void) +{ + int i; + unsigned char key = 0x6a; + + outb(PNPADDR, 0); + outb(PNPADDR, 0); + + for (i = 0; i < 32; i++) { + outb(PNPADDR, key); + key = (key >> 1) | + (((key & 1) == !(key & 2)) << 7); + } +} + +int +isapnp_finddev(int id, int *iobase, int *dmachan) +{ + int csn; + + outb(PNPADDR, CONTROL); + outb(PNPWDATA, 2); /* XXX force wait for key */ + + /* scan all allowed data ports (ch. 3.1) */ + for (pnpdataport = PNPRDATAMIN; pnpdataport <= PNPRDATAMAX; + pnpdataport += 4) { + int res, found = 0; + + pnpinit(); /* initiation sequence */ + + outb(PNPADDR, CONTROL); + outb(PNPWDATA, 4); /* CSN=0 - only these respond to + * WAKE[0] */ + + outb(PNPADDR, WAKE); + outb(PNPWDATA, 0); /* put into isolation state */ + + outb(PNPADDR, DATAPORT); + outb(PNPWDATA, pnpdataport >> 2); /* set READ_DATA port */ + + csn = 0; + do { + res = pnpisol(++csn); + + if ((res) == id) { + if (iobase) + *iobase = getiobase(0); + if (dmachan) + *dmachan = getdmachan(0); + found = 1; + } + pnpisolreset(); + } while ((res != 0) && (res != -1)); + + outb(PNPADDR, CONTROL); + outb(PNPWDATA, 2); /* return to wait for key */ + + if (csn > 1) /* at least 1 board found */ + return !found; + + /* if no board found, try next dataport */ + } + return -1; /* nothing found */ +} diff --git a/sys/arch/i386/stand/lib/isapnpvar.h b/sys/arch/i386/stand/lib/isapnpvar.h new file mode 100644 index 000000000..41b05feff --- /dev/null +++ b/sys/arch/i386/stand/lib/isapnpvar.h @@ -0,0 +1,29 @@ +/* $NetBSD: isapnpvar.h,v 1.4 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +int isapnp_finddev(int, int*, int*); diff --git a/sys/arch/i386/stand/lib/libi386.h b/sys/arch/i386/stand/lib/libi386.h new file mode 100644 index 000000000..2fb0ec5cb --- /dev/null +++ b/sys/arch/i386/stand/lib/libi386.h @@ -0,0 +1,145 @@ +/* $NetBSD: libi386.h,v 1.38 2011/11/28 07:56:54 tls Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +typedef unsigned long physaddr_t; + +/* this is in startup code */ +void vpbcopy(const void *, void *, size_t); +void pvbcopy(const void *, void *, size_t); +void pbzero(void *, size_t); +physaddr_t vtophys(void *); + +ssize_t pread(int, void *, size_t); +void startprog(physaddr_t, int, unsigned long *, physaddr_t); +void multiboot(physaddr_t, physaddr_t, physaddr_t); + +int exec_netbsd(const char *, physaddr_t, int, int, void (*)(void)); +int exec_multiboot(const char *, char *); + +void delay(int); +int getbasemem(void); +int getextmemx(void); +int getextmem1(void); +int biosvideomode(void); +#ifdef CONSERVATIVE_MEMDETECT +#define getextmem() getextmem1() +#else +#define getextmem() getextmemx() +#endif +void printmemlist(void); +void reboot(void); +void gateA20(void); + +void clear_pc_screen(void); +void initio(int); +#define CONSDEV_PC 0 +#define CONSDEV_COM0 1 +#define CONSDEV_COM1 2 +#define CONSDEV_COM2 3 +#define CONSDEV_COM3 4 +#define CONSDEV_COM0KBD 5 +#define CONSDEV_COM1KBD 6 +#define CONSDEV_COM2KBD 7 +#define CONSDEV_COM3KBD 8 +#define CONSDEV_AUTO (-1) +int iskey(int); +char awaitkey(int, int); +void wait_sec(int); + +/* this is in "user code"! */ +int parsebootfile(const char *, char **, char **, int *, int *, const char **); + +#ifdef XMS +physaddr_t ppbcopy(physaddr_t, physaddr_t, int); +int checkxms(void); +physaddr_t xmsalloc(int); +#endif + +/* parseutils.c */ +char *gettrailer(char *); +int parseopts(const char *, int *); +int parseboot(char *, char **, int *); + +/* menuutils.c */ +struct bootblk_command { + const char *c_name; + void (*c_fn)(char *); +}; +void bootmenu(void); +void docommand(char *); + +/* in "user code": */ +void command_help(char *); +extern const struct bootblk_command commands[]; + +/* asm bios/dos calls */ +__compactcall int biosdisk_extread(int, void *); +int biosdisk_read(int, int, int, int, int, void *); +__compactcall int biosdisk_reset(int); + +__compactcall int biosgetrtc(u_long *); +int biosgetsystime(void); +int comgetc(int); +void cominit(int); +__compactcall int computc(int, int); +int comstatus(int); +int congetc(void); +int conisshift(void); +int coniskey(void); +__compactcall void conputc(int); +void conclr(void); + +int getextmem2(int *); +__compactcall int getextmemps2(void *); +int getmementry(int *, int *); + +__compactcall int biosdisk_int13ext(int); +__compactcall int biosdisk_getinfo(int); +struct biosdisk_extinfo; +__compactcall int biosdisk_getextinfo(int, struct biosdisk_extinfo *); +int get_harddrives(void); +void biosdisk_probe(void); + +int pcibios_cfgread(unsigned int, int, int *); +int pcibios_cfgwrite(unsigned int, int, int); +int pcibios_finddev(int, int, int, unsigned int *); +int pcibios_present(int *); + +void dosclose(int); +int dosopen(char *); +int dosread(int, char *, int); +int dosseek(int, int, int); +extern int doserrno; /* in dos_file.S */ + +void module_add(char *); +void splash_add(char *); +void rnd_add(char *); +void userconf_add(char *); + +struct btinfo_framebuffer; +void framebuffer_configure(struct btinfo_framebuffer *); diff --git a/sys/arch/i386/stand/lib/menuutils.c b/sys/arch/i386/stand/lib/menuutils.c new file mode 100644 index 000000000..92904ac70 --- /dev/null +++ b/sys/arch/i386/stand/lib/menuutils.c @@ -0,0 +1,84 @@ +/* $NetBSD: menuutils.c,v 1.3 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1996, 1997 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996, 1997 + * Perry E. Metzger. All rights reserved. + * Copyright (c) 1997 + * Jason R. Thorpe. All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "libi386.h" + +void +docommand(char *arg) +{ + char *options; + int i; + + options = gettrailer(arg); + + for (i = 0; commands[i].c_name != NULL; i++) { + if (strcmp(arg, commands[i].c_name) == 0) { + (*commands[i].c_fn)(options); + return; + } + } + + printf("unknown command\n"); + command_help(NULL); +} + +void +bootmenu(void) +{ + char input[80]; + + for (;;) { + char *c = input; + + input[0] = '\0'; + printf("> "); + gets(input); + + /* + * Skip leading whitespace. + */ + while (*c == ' ') + c++; + if (*c) + docommand(c); + } +} diff --git a/sys/arch/i386/stand/lib/message.S b/sys/arch/i386/stand/lib/message.S new file mode 100644 index 000000000..21a708190 --- /dev/null +++ b/sys/arch/i386/stand/lib/message.S @@ -0,0 +1,79 @@ +/* $NetBSD: message.S,v 1.4 2009/11/19 22:10:03 dsl Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + .global message, message_1 + +#if defined(BOOT_MSG_COM0) && !defined(COM_PORT_VAL) +#define COM_PORT_VAL $0x3f8 /* Value for COM1 */ +#endif + +/* + * message: write the error message in %ds:%esi to the console + */ +message: +/* + * BIOS call "INT 10H Function 0Eh" to write character to console + * Call with %ah = 0x0e + * %al = character + * %bh = page + * %bl = foreground color + */ + .code16 + pusha +message_1: /* for dump_eax */ + lodsb +1: +#ifdef COM_PORT_VAL + mov COM_PORT_VAL, %dx + outb %al, %dx + add $5, %dl +2: inb %dx + test $0x40, %al + jz 2b +#else + movb $0x0e, %ah + movw $0x0001, %bx + int $0x10 +#endif + lodsb + testb %al, %al + jnz 1b + +#ifdef MESSAGE_PAUSE + /* Delay for about 1 second to allow message to be read */ + movb $0x86, %ah + mov $16, %cx /* about a second */ + int $0x15 /* delay cx:dx usecs */ +#endif + popa + ret diff --git a/sys/arch/i386/stand/lib/message32.S b/sys/arch/i386/stand/lib/message32.S new file mode 100644 index 000000000..45cd286ca --- /dev/null +++ b/sys/arch/i386/stand/lib/message32.S @@ -0,0 +1,87 @@ +/* $NetBSD: message32.S,v 1.1 2009/11/19 22:13:17 dsl Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* + * Output messages directly to serial port from 32bit mode. + * Useful for debugging when the real-prot is suspect. + * + * %ds:dump_eax_buff must be somewhere it is safe to write 12 bytes. + */ + +#ifndef COM_PORT_VAL +#define COM_PORT_VAL $0x3f8 /* Standard address COM1 (dty0) */ +#endif + + .globl message32 + .code32 +message32: + pusha +message32_1: + lodsb +2: + mov COM_PORT_VAL, %dx + outb %al, %dx + add $5, %dl +3: inb %dx + test $0x40, %al + jz 3b + + lodsb + test %al, %al + jnz 2b + popa + ret + + .globl dump_eax32 +dump_eax32: + pusha + movl $dump_eax_buff, %esi + mov %esi, %edi + push $8 + pop %ecx +1: roll $4, %eax + push %eax + andb $0x0f, %al + addb $0x30, %al /* 30..3f - clear AF */ +#if 1 /* 5 bytes to generate real hex... */ + daa /* 30..39, 40..45 */ + addb $0xc0, %al /* f0..f9, 00..05 */ + adcb $0x40, %al /* 30..39, 41..46 */ +#endif + movb %al,(%edi) + inc %edi + pop %eax + loop 1b + push $0x20 /* space + 3 NULs */ + pop (%edi) + jmp message32_1 diff --git a/sys/arch/i386/stand/lib/multiboot.S b/sys/arch/i386/stand/lib/multiboot.S new file mode 100644 index 000000000..de5225944 --- /dev/null +++ b/sys/arch/i386/stand/lib/multiboot.S @@ -0,0 +1,124 @@ +/* $NetBSD: multiboot.S,v 1.1 2008/10/11 11:06:20 joerg Exp $ */ + +/* starts program in protected mode / flat space + with given stackframe + needs global variables flatcodeseg and flatdataseg + (gdt offsets) + derived from: NetBSD:sys/arch/i386/stand/lib/startprog.S + */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#define MULTIBOOT_INFO_MAGIC 0x2BADB002 + +/* + * multiboot(phyaddr,header,stack) + * start the program on protected mode where phyaddr is the entry point + */ +ENTRY(multiboot) + pushl %ebp + movl %esp, %ebp + + # prepare a new stack + movl $flatdataseg, %eax + movw %ax, %es # for arg copy + movl 16(%ebp), %ebx # stack + subl $4,%ebx + movl %ebx, %edi + + movl 12(%ebp), %ebx # header + movl 8(%ebp), %ecx # entry + + # set new stackptr (movsl decd sp 1 more -> dummy return address) + movw %ax, %ss + movl %edi, %esp + + # push on our entry address + movl $flatcodeseg, %eax # segment + pushl %eax + pushl %ecx #entry + + # convert over the other data segs + movl $flatdataseg, %eax + mov %ax, %ds + mov %ax, %es + + movl $MULTIBOOT_INFO_MAGIC, %eax + # convert the PC (and code seg) + lret diff --git a/sys/arch/i386/stand/lib/netif/3c509.c b/sys/arch/i386/stand/lib/netif/3c509.c new file mode 100644 index 000000000..ea60802bd --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/3c509.c @@ -0,0 +1,227 @@ +/* $NetBSD: 3c509.c,v 1.10 2008/12/14 18:46:33 christos Exp $ */ + +/* stripped down from freebsd:sys/i386/netboot/3c509.c */ + +/************************************************************************** +NETBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters. + Date: Mar 22 1995 + + This code is based heavily on David Greenman's if_ed.c driver and + Andres Vega Garcia's if_ep.c driver. + + Copyright (C) 1993-1994, David Greenman, Martin Renters. + Copyright (C) 1993-1995, Andres Vega Garcia. + Copyright (C) 1995, Serge Babkin. + This software may be used, modified, copied, distributed, and sold, in + both source and binary form provided that the above copyright and these + terms are retained. Under no circumstances are the authors responsible for + the proper functioning of this software, nor do the authors assume any + responsibility for damages incurred with its use. + +3c509 support added by Serge Babkin (babkin@hq.icb.chel.su) + +3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp + +***************************************************************************/ + +#include +#include + +#include +#include + +#include +#ifdef _STANDALONE +#include +#endif + +#include "etherdrv.h" +#include "3c509.h" + +unsigned ether_medium; +unsigned short eth_base; + +extern void epreset(void); +extern int ep_get_e(int); + +static int send_ID_sequence(int); +static int get_eeprom_data(int, int); + +u_char eth_myaddr[6]; + +static struct mtabentry { + int address_cfg; /* configured connector */ + int config_bit; /* connector present */ + char *name; +} mediatab[] = { /* indexed by media type - etherdrv.h */ + {3, IS_BNC, "BNC"}, + {0, IS_UTP, "UTP"}, + {1, IS_AUI, "AUI"}, +}; + +#ifdef _STANDALONE +static struct btinfo_netif bi_netif; +#endif + +#ifndef _STANDALONE +extern int mapio(void); +#endif + +/************************************************************************** +ETH_PROBE - Look for an adapter +***************************************************************************/ +int +EtherInit(unsigned char *myadr) +{ + /* common variables */ + int i; + /* variables for 3C509 */ + int data, j, id_port = EP_ID_PORT; + u_short k; +/* int ep_current_tag = EP_LAST_TAG + 1; */ + u_short *p; + struct mtabentry *m; + +#ifndef _STANDALONE + if (mapio()) { + printf("no IO access\n"); + return 0; + } +#endif + + /********************************************************* + Search for 3Com 509 card + ***********************************************************/ +/* + ep_current_tag--; +*/ + + /* Look for the ISA boards. Init and leave them actived */ + /* search for the first card, ignore all others */ + outb(id_port, 0xc0); /* Global reset */ + delay(1000); +/* + for (i = 0; i < EP_MAX_BOARDS; i++) { +*/ + outb(id_port, 0); + outb(id_port, 0); + send_ID_sequence(id_port); + + data = get_eeprom_data(id_port, EEPROM_MFG_ID); + if (data != MFG_ID) + return 0; + + /* resolve contention using the Ethernet address */ + for (j = 0; j < 3; j++) + data = get_eeprom_data(id_port, j); + + eth_base = + (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; + outb(id_port, EP_LAST_TAG); /* tags board */ + outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG); +/* + ep_current_tag--; + break; + } + + if (i == EP_MAX_BOARDS) + return 0; +*/ + + /* + * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be + * 0x9[0-f]50 + */ + GO_WINDOW(0); + k = (u_int)ep_get_e(EEPROM_PROD_ID); + if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) + return 0; + + printf("3C5x9 board on ISA at 0x%x - ", eth_base); + + /* test for presence of connectors */ + i = inw(IS_BASE + EP_W0_CONFIG_CTRL); + j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14; + + for (ether_medium = 0, m = mediatab; + ether_medium < sizeof(mediatab) / sizeof(mediatab[0]); + ether_medium++, m++) { + if (j == m->address_cfg) { + if (!(i & m->config_bit)) { + printf("%s not present\n", m->name); + return 0; + } + printf("using %s\n", m->name); + goto ok; + } + } + printf("unknown connector\n"); + return 0; + +ok: + /* + * Read the station address from the eeprom + */ + p = (u_short *) eth_myaddr; + for (i = 0; i < 3; i++) { + u_short help; + GO_WINDOW(0); + help = ep_get_e(i); + p[i] = ((help & 0xff) << 8) | ((help & 0xff00) >> 8); + GO_WINDOW(2); + outw(BASE + EP_W2_ADDR_0 + (i * 2), help); + } + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i]; + + epreset(); + +#ifdef _STANDALONE + strncpy(bi_netif.ifname, "ep", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_ISA; + bi_netif.addr.iobase = eth_base; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + + return 1; +} + +static int +send_ID_sequence(int port) +{ + int cx, al; + + for (al = 0xff, cx = 0; cx < 255; cx++) { + outb(port, al); + al <<= 1; + if (al & 0x100) + al ^= 0xcf; + } + return 1; +} + +/* + * We get eeprom data from the id_port given an offset into the eeprom. + * Basically; after the ID_sequence is sent to all of the cards; they enter + * the ID_CMD state where they will accept command requests. 0x80-0xbf loads + * the eeprom data. We then read the port 16 times and with every read; the + * cards check for contention (ie: if one card writes a 0 bit and another + * writes a 1 bit then the host sees a 0. At the end of the cycle; each card + * compares the data on the bus; if there is a difference then that card goes + * into ID_WAIT state again). In the meantime; one bit of data is returned in + * the AX register which is conveniently returned to us by inb(). Hence; we + * read 16 times getting one bit of data with each read. + */ +static int +get_eeprom_data(int id_port, int offset) +{ + int i, data = 0; + outb(id_port, 0x80 + offset); + delay(1000); + for (i = 0; i < 16; i++) + data = (data << 1) | (inw(id_port) & 1); + return data; +} diff --git a/sys/arch/i386/stand/lib/netif/3c509.h b/sys/arch/i386/stand/lib/netif/3c509.h new file mode 100644 index 000000000..eb6ca4a16 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/3c509.h @@ -0,0 +1,393 @@ +/* $NetBSD: 3c509.h,v 1.6 2006/11/24 22:52:16 wiz Exp $ */ + +/* + * Copyright (c) 1993 Herb Peyerl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by: + * + October 2, 1994 + + Modified by: Andres Vega Garcia + + INRIA - Sophia Antipolis, France + e-mail: avega@sophia.inria.fr + finger: avega@pax.inria.fr + + */ + +/* + * Ethernet software status per interface. + */ +/* + * Some global constants + */ +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 +#define ETHER_ADDR_LEN 6 + +#define TX_INIT_RATE 16 +#define TX_INIT_MAX_RATE 64 +#define RX_INIT_LATENCY 64 +#define RX_INIT_EARLY_THRESH 64 +#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */ +#define MIN_RX_EARLY_THRESHL 4 + +#define EEPROMSIZE 0x40 +#define MAX_EEPROMBUSY 1000 +#define EP_LAST_TAG 0xd7 +#define EP_MAX_BOARDS 16 +#define EP_ID_PORT 0x100 + +/* + * some macros to acces long named fields + */ +#define IS_BASE (eth_base) +#define BASE (eth_base) + +/* + * Commands to read/write EEPROM through EEPROM command register (Window 0, + * Offset 0xa) + */ +#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ +#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ +#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ +#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ + +#define EEPROM_BUSY (1<<15) +#define EEPROM_TST_MODE (1<<14) + +/* + * Some short functions, worth to let them be a macro + */ +#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY) +#define GO_WINDOW(x) outw(BASE+EP_COMMAND, WINDOW_SELECT|(x)) + +/************************************************************************** + * * + * These define the EEPROM data structure. They are used in the probe + * function to verify the existence of the adapter after having sent + * the ID_Sequence. + * + * There are others but only the ones we use are defined here. + * + **************************************************************************/ + +#define EEPROM_NODE_ADDR_0 0x0 /* Word */ +#define EEPROM_NODE_ADDR_1 0x1 /* Word */ +#define EEPROM_NODE_ADDR_2 0x2 /* Word */ +#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ +#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ +#define EEPROM_ADDR_CFG 0x8 /* Base addr */ +#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ + +/************************************************************************** + * * + * These are the registers for the 3Com 3c509 and their bit patterns when * + * applicable. They have been taken out of the "EtherLink III Parallel * + * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * + * from 3com. * + * * + **************************************************************************/ + +#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a + * command reg. */ +#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status + * reg. */ +#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window + * reg. */ +/* + * Window 0 registers. Setup. + */ +/* Write */ +#define EP_W0_EEPROM_DATA 0x0c +#define EP_W0_EEPROM_COMMAND 0x0a +#define EP_W0_RESOURCE_CFG 0x08 +#define EP_W0_ADDRESS_CFG 0x06 +#define EP_W0_CONFIG_CTRL 0x04 +/* Read */ +#define EP_W0_PRODUCT_ID 0x02 +#define EP_W0_MFG_ID 0x00 + +/* + * Window 1 registers. Operating Set. + */ +/* Write */ +#define EP_W1_TX_PIO_WR_2 0x02 +#define EP_W1_TX_PIO_WR_1 0x00 +/* Read */ +#define EP_W1_FREE_TX 0x0c +#define EP_W1_TX_STATUS 0x0b /* byte */ +#define EP_W1_TIMER 0x0a /* byte */ +#define EP_W1_RX_STATUS 0x08 +#define EP_W1_RX_PIO_RD_2 0x02 +#define EP_W1_RX_PIO_RD_1 0x00 + +/* + * Window 2 registers. Station Address Setup/Read + */ +/* Read/Write */ +#define EP_W2_ADDR_5 0x05 +#define EP_W2_ADDR_4 0x04 +#define EP_W2_ADDR_3 0x03 +#define EP_W2_ADDR_2 0x02 +#define EP_W2_ADDR_1 0x01 +#define EP_W2_ADDR_0 0x00 + +/* + * Window 3 registers. FIFO Management. + */ +/* Read */ +#define EP_W3_FREE_TX 0x0c +#define EP_W3_FREE_RX 0x0a + +/* + * Window 4 registers. Diagnostics. + */ +/* Read/Write */ +#define EP_W4_MEDIA_TYPE 0x0a +#define EP_W4_CTRLR_STATUS 0x08 +#define EP_W4_NET_DIAG 0x06 +#define EP_W4_FIFO_DIAG 0x04 +#define EP_W4_HOST_DIAG 0x02 +#define EP_W4_TX_DIAG 0x00 + +/* + * Window 5 Registers. Results and Internal status. + */ +/* Read */ +#define EP_W5_READ_0_MASK 0x0c +#define EP_W5_INTR_MASK 0x0a +#define EP_W5_RX_FILTER 0x08 +#define EP_W5_RX_EARLY_THRESH 0x06 +#define EP_W5_TX_AVAIL_THRESH 0x02 +#define EP_W5_TX_START_THRESH 0x00 + +/* + * Window 6 registers. Statistics. + */ +/* Read/Write */ +#define TX_TOTAL_OK 0x0c +#define RX_TOTAL_OK 0x0a +#define TX_DEFERRALS 0x08 +#define RX_FRAMES_OK 0x07 +#define TX_FRAMES_OK 0x06 +#define RX_OVERRUNS 0x05 +#define TX_COLLISIONS 0x04 +#define TX_AFTER_1_COLLISION 0x03 +#define TX_AFTER_X_COLLISIONS 0x02 +#define TX_NO_SQE 0x01 +#define TX_CD_LOST 0x00 + +/**************************************** + * + * Register definitions. + * + ****************************************/ + +/* + * Command register. All windows. + * + * 16 bit register. + * 15-11: 5-bit code for command to be executed. + * 10-0: 11-bit arg if any. For commands with no args; + * this can be set to anything. + */ +#define GLOBAL_RESET (u_short) 0x0000 /* Wait at least 1ms + * after issuing */ +#define WINDOW_SELECT (u_short) (0x1<<11) +#define START_TRANSCEIVER (u_short) (0x2<<11) /* Read ADDR_CFG reg to + * determine whether + * this is needed. If + * so; wait 800 uSec + * before using trans- + * ceiver. */ +#define RX_DISABLE (u_short) (0x3<<11) /* state disabled on + * power-up */ +#define RX_ENABLE (u_short) (0x4<<11) +#define RX_RESET (u_short) (0x5<<11) +#define RX_DISCARD_TOP_PACK (u_short) (0x8<<11) +#define TX_ENABLE (u_short) (0x9<<11) +#define TX_DISABLE (u_short) (0xa<<11) +#define TX_RESET (u_short) (0xb<<11) +#define REQ_INTR (u_short) (0xc<<11) +#define SET_INTR_MASK (u_short) (0xe<<11) +#define SET_RD_0_MASK (u_short) (0xf<<11) +#define SET_RX_FILTER (u_short) (0x10<<11) +#define FIL_INDIVIDUAL (u_short) (0x1) +#define FIL_GROUP (u_short) (0x2) +#define FIL_BRDCST (u_short) (0x4) +#define FIL_ALL (u_short) (0x8) +#define SET_RX_EARLY_THRESH (u_short) (0x11<<11) +#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11) +#define SET_TX_START_THRESH (u_short) (0x13<<11) +#define STATS_ENABLE (u_short) (0x15<<11) +#define STATS_DISABLE (u_short) (0x16<<11) +#define STOP_TRANSCEIVER (u_short) (0x17<<11) +/* + * The following C_* acknowledge the various interrupts. Some of them don't + * do anything. See the manual. + */ +#define ACK_INTR (u_short) (0x6800) +#define C_INTR_LATCH (u_short) (ACK_INTR|0x1) +#define C_CARD_FAILURE (u_short) (ACK_INTR|0x2) +#define C_TX_COMPLETE (u_short) (ACK_INTR|0x4) +#define C_TX_AVAIL (u_short) (ACK_INTR|0x8) +#define C_RX_COMPLETE (u_short) (ACK_INTR|0x10) +#define C_RX_EARLY (u_short) (ACK_INTR|0x20) +#define C_INT_RQD (u_short) (ACK_INTR|0x40) +#define C_UPD_STATS (u_short) (ACK_INTR|0x80) + +/* + * Status register. All windows. + * + * 15-13: Window number(0-7). + * 12: Command_in_progress. + * 11: reserved. + * 10: reserved. + * 9: reserved. + * 8: reserved. + * 7: Update Statistics. + * 6: Interrupt Requested. + * 5: RX Early. + * 4: RX Complete. + * 3: TX Available. + * 2: TX Complete. + * 1: Adapter Failure. + * 0: Interrupt Latch. + */ +#define S_INTR_LATCH (u_short) (0x1) +#define S_CARD_FAILURE (u_short) (0x2) +#define S_TX_COMPLETE (u_short) (0x4) +#define S_TX_AVAIL (u_short) (0x8) +#define S_RX_COMPLETE (u_short) (0x10) +#define S_RX_EARLY (u_short) (0x20) +#define S_INT_RQD (u_short) (0x40) +#define S_UPD_STATS (u_short) (0x80) +#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\ + S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY) +#define S_COMMAND_IN_PROGRESS (u_short) (0x1000) + +/* + * FIFO Registers. + * RX Status. Window 1/Port 08 + * + * 15: Incomplete or FIFO empty. + * 14: 1: Error in RX Packet 0: Incomplete or no error. + * 13-11: Type of error. + * 1000 = Overrun. + * 1011 = Run Packet Error. + * 1100 = Alignment Error. + * 1101 = CRC Error. + * 1001 = Oversize Packet Error (>1514 bytes) + * 0010 = Dribble Bits. + * (all other error codes, no errors.) + * + * 10-0: RX Bytes (0-1514) + */ +#define ERR_RX_INCOMPLETE (u_short) (0x1<<15) +#define ERR_RX (u_short) (0x1<<14) +#define ERR_RX_OVERRUN (u_short) (0x8<<11) +#define ERR_RX_RUN_PKT (u_short) (0xb<<11) +#define ERR_RX_ALIGN (u_short) (0xc<<11) +#define ERR_RX_CRC (u_short) (0xd<<11) +#define ERR_RX_OVERSIZE (u_short) (0x9<<11) +#define ERR_RX_DRIBBLE (u_short) (0x2<<11) + +/* + * FIFO Registers. + * TX Status. Window 1/Port 0B + * + * Reports the transmit status of a completed transmission. Writing this + * register pops the transmit completion stack. + * + * Window 1/Port 0x0b. + * + * 7: Complete + * 6: Interrupt on successful transmission requested. + * 5: Jabber Error (TP Only, TX Reset required. ) + * 4: Underrun (TX Reset required. ) + * 3: Maximum Collisions. + * 2: TX Status Overflow. + * 1-0: Undefined. + * + */ +#define TXS_COMPLETE 0x80 +#define TXS_SUCCES_INTR_REQ 0x40 +#define TXS_JABBER 0x20 +#define TXS_UNDERRUN 0x10 +#define TXS_MAX_COLLISION 0x8 +#define TXS_STATUS_OVERFLOW 0x4 + +/* + * Configuration control register. + * Window 0/Port 04 + */ +/* Read */ +#define IS_AUI (1<<13) +#define IS_BNC (1<<12) +#define IS_UTP (1<<9) +/* Write */ +#define ENABLE_DRQ_IRQ 0x0001 +#define W0_P4_CMD_RESET_ADAPTER 0x4 +#define W0_P4_CMD_ENABLE_ADAPTER 0x1 +/* + * Media type and status. + * Window 4/Port 0A + */ +#define ENABLE_UTP 0xc0 +#define DISABLE_UTP 0x0 + +/* + * Resource control register + */ + +#define SET_IRQ(i) ( ((i)<<12) | 0xF00) /* set IRQ i */ + +/* + * Receive status register + */ + +#define RX_BYTES_MASK (u_short) (0x07ff) +#define RX_ERROR 0x4000 +#define RX_INCOMPLETE 0x8000 + + +/* + * Misc defines for various things. + */ +#define ACTIVATE_ADAPTER_TO_CONFIG 0xff /* to the id_port */ +#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */ +#define PROD_ID 0x9150 + +#define AUI 0x1 +#define BNC 0x2 +#define UTP 0x4 + +#define ETHER_ADDR_LEN 6 +#define ETHER_MAX 1536 +#define RX_BYTES_MASK (u_short) (0x07ff) + + /* EISA support */ +#define EP_EISA_START 0x1000 +#define EP_EISA_W0 0x0c80 diff --git a/sys/arch/i386/stand/lib/netif/3c590.c b/sys/arch/i386/stand/lib/netif/3c590.c new file mode 100644 index 000000000..44dd5da14 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/3c590.c @@ -0,0 +1,161 @@ +/* $NetBSD: 3c590.c,v 1.15 2008/12/14 18:46:33 christos Exp $ */ + +/* stripped down from freebsd:sys/i386/netboot/3c509.c */ + + +/************************************************************************** +NETBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters. + Date: Mar 22 1995 + + This code is based heavily on David Greenman's if_ed.c driver and + Andres Vega Garcia's if_ep.c driver. + + Copyright (C) 1993-1994, David Greenman, Martin Renters. + Copyright (C) 1993-1995, Andres Vega Garcia. + Copyright (C) 1995, Serge Babkin. + This software may be used, modified, copied, distributed, and sold, in + both source and binary form provided that the above copyright and these + terms are retained. Under no circumstances are the authors responsible for + the proper functioning of this software, nor do the authors assume any + responsibility for damages incurred with its use. + +3c509 support added by Serge Babkin (babkin@hq.icb.chel.su) + +3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp + +***************************************************************************/ + +#include +#include + +#include + +#include +#include + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +#include +#include +#endif + +#include "etherdrv.h" +#include "3c509.h" + +#define EP_W3_INTERNAL_CONFIG 0x00 /* 32 bits */ +#define EP_W3_RESET_OPTIONS 0x08 /* 16 bits */ + +unsigned ether_medium; +unsigned short eth_base; + +extern void epreset(void); +extern int ep_get_e(int); + +u_char eth_myaddr[6]; + +static struct mtabentry { + int address_cfg; /* configured connector */ + int config_bit; /* connector present */ + char *name; +} mediatab[] = { /* indexed by media type - etherdrv.h */ + {3, 0x10, "BNC"}, + {0, 0x08, "UTP"}, + {1, 0x20, "AUI"}, + {6, 0x40, "MII"}, +}; + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +static struct btinfo_netif bi_netif; +#endif + +/************************************************************************** +ETH_PROBE - Look for an adapter +***************************************************************************/ +int +EtherInit(unsigned char *myadr) +{ + /* common variables */ + int i, j; + /* variables for 3C509 */ + u_short *p; + struct mtabentry *m; + + /********************************************************* + Search for 3Com 590 card + ***********************************************************/ + + pcihdl_t hdl; + int iobase; + + if (pcicheck() == -1) { + printf("cannot access PCI\n"); + return 0; + } + + if (pcifinddev(0x10b7, 0x5900, &hdl) && + pcifinddev(0x10b7, 0x5950, &hdl) && + pcifinddev(0x10b7, 0x9000, &hdl) && + pcifinddev(0x10b7, 0x9001, &hdl) && + pcifinddev(0x10b7, 0x9050, &hdl)) { + printf("cannot find 3c59x / 3c90x\n"); + return 0; + } + + if (pcicfgread(&hdl, 0x10, &iobase) || !(iobase & 1)) { + printf("cannot map IO space\n"); + return 0; + } + eth_base = iobase & 0xfffffffc; + + /* test for presence of connectors */ + GO_WINDOW(3); + i = inb(IS_BASE + EP_W3_RESET_OPTIONS); + j = (inw(IS_BASE + EP_W3_INTERNAL_CONFIG + 2) >> 4) & 7; + + GO_WINDOW(0); + + for (ether_medium = 0, m = mediatab; + ether_medium < sizeof(mediatab) / sizeof(mediatab[0]); + ether_medium++, m++) { + if (j == m->address_cfg) { + if (!(i & m->config_bit)) { + printf("%s not present\n", m->name); + return 0; + } + printf("using %s\n", m->name); + goto ok; + } + } + printf("unknown connector\n"); + return 0; + + ok: + /* + * Read the station address from the eeprom + */ + p = (u_short *) eth_myaddr; + for (i = 0; i < 3; i++) { + u_short help; + GO_WINDOW(0); + help = ep_get_e(i); + p[i] = ((help & 0xff) << 8) | ((help & 0xff00) >> 8); + GO_WINDOW(2); + outw(BASE + EP_W2_ADDR_0 + (i * 2), help); + } + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i]; + + epreset(); + + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) + strncpy(bi_netif.ifname, "ep", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_PCI; + bi_netif.addr.tag = hdl; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + + return 1; +} diff --git a/sys/arch/i386/stand/lib/netif/3c90xb.c b/sys/arch/i386/stand/lib/netif/3c90xb.c new file mode 100644 index 000000000..602d0ab1f --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/3c90xb.c @@ -0,0 +1,449 @@ +/* $NetBSD: 3c90xb.c,v 1.14 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1999 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +struct mbuf; /* XXX */ +typedef int bus_dmamap_t; /* XXX */ +#include +#include + +#include + +#include +#include + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +#include +#include +#endif + +#include "etherdrv.h" + +#define RECVBUF_SIZE 1600 /* struct ex_upd + packet */ + +#ifdef _STANDALONE + +static pcihdl_t mytag; +static char recvbuf[RECVBUF_SIZE]; +#define RECVBUF_PHYS vtophys(recvbuf) +#define RECVBUF_VIRT ((void *)recvbuf) +static struct ex_dpd sndbuf; +#define SNDBUF_PHYS vtophys(&sndbuf) +#define SNDBUF_VIRT ((void *)&sndbuf) + +#else /* !standalone, userspace testing environment */ + +#define PCI_MODE1_ENABLE 0x80000000UL +#define PCIBUSNO 1 +#define PCIDEVNO 4 +static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIBUSNO << 16) | (PCIDEVNO << 11); + +extern void *mapmem(int, int); +void *dmamem; /* virtual */ +#define DMABASE 0x3ffd800 +#define DMASIZE 10240 +#define RECVBUF_PHYS DMABASE +#define RECVBUF_VIRT dmamem +#define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE) +#define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE)) + +#endif /* _STANDALONE */ + + +#define CSR_READ_1(reg) inb(iobase + (reg)) +#define CSR_READ_2(reg) inw(iobase + (reg)) +#define CSR_READ_4(reg) inl(iobase + (reg)) +#define CSR_WRITE_1(reg, val) outb(iobase + (reg), val) +#define CSR_WRITE_2(reg, val) outw(iobase + (reg), val) +#define CSR_WRITE_4(reg, val) outl(iobase + (reg), val) + +#undef GO_WINDOW +#define GO_WINDOW(x) CSR_WRITE_2(ELINK_COMMAND, WINDOW_SELECT | x) + +static int iobase; +static u_char myethaddr[6]; +unsigned ether_medium; + +static struct { + int did; + int mii; +} excards[] = { + {0x9005, 0}, /* 3c900b Combo */ + {0x9055, 1}, /* 3c905b TP */ + {0x9058, 0}, /* 3c905b Combo */ + {-1} +}, *excard; + +static struct mtabentry { + int address_cfg; /* configured connector */ + int config_bit; /* connector present */ + char *name; +} mediatab[] = { /* indexed by media type - etherdrv.h */ + {ELINKMEDIA_10BASE_2, ELINK_PCI_BNC, "BNC"}, + {ELINKMEDIA_10BASE_T, ELINK_PCI_10BASE_T, "UTP"}, + {ELINKMEDIA_AUI, ELINK_PCI_AUI, "AUI"}, + {ELINKMEDIA_MII, ELINK_PCI_100BASE_MII, "MII"}, + {ELINKMEDIA_100BASE_TX, ELINK_PCI_100BASE_TX, "100TX"}, +}; + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +static struct btinfo_netif bi_netif; +#endif + +#define ex_waitcmd() \ + do { \ + while (CSR_READ_2(ELINK_STATUS) & COMMAND_IN_PROGRESS) \ + continue; \ + } while (0) + +void ex_reset(void); +uint16_t ex_read_eeprom(int); +static int ex_eeprom_busy(void); +void ex_init(void); +void ex_set_media(void); + +void +ex_reset(void) +{ + CSR_WRITE_2(ELINK_COMMAND, GLOBAL_RESET); + delay(100000); + ex_waitcmd(); +} + +/* + * Read EEPROM data. + * XXX what to do if EEPROM doesn't unbusy? + */ +uint16_t +ex_read_eeprom(int offset) +{ + uint16_t data = 0; + + GO_WINDOW(0); + if (ex_eeprom_busy()) + goto out; + CSR_WRITE_1(ELINK_W0_EEPROM_COMMAND, READ_EEPROM | (offset & 0x3f)); + if (ex_eeprom_busy()) + goto out; + data = CSR_READ_2(ELINK_W0_EEPROM_DATA); +out: + return data; +} + +static int +ex_eeprom_busy(void) +{ + int i = 100; + + while (i--) { + if (!(CSR_READ_2(ELINK_W0_EEPROM_COMMAND) & EEPROM_BUSY)) + return 0; + delay(100); + } + printf("\nex: eeprom stays busy.\n"); + return 1; +} + +/* + * Bring device up. + */ +void +ex_init(void) +{ + int i; + + ex_waitcmd(); + EtherStop(); + + /* + * Set the station address and clear the station mask. The latter + * is needed for 90x cards, 0 is the default for 90xB cards. + */ + GO_WINDOW(2); + for (i = 0; i < 6; i++) { + CSR_WRITE_1(ELINK_W2_ADDR_0 + i, + myethaddr[i]); + CSR_WRITE_1(ELINK_W2_RECVMASK_0 + i, 0); + } + + GO_WINDOW(3); + + CSR_WRITE_2(ELINK_COMMAND, RX_RESET); + ex_waitcmd(); + CSR_WRITE_2(ELINK_COMMAND, TX_RESET); + ex_waitcmd(); + + CSR_WRITE_2(ELINK_COMMAND, SET_INTR_MASK | 0); /* disable */ + CSR_WRITE_2(ELINK_COMMAND, ACK_INTR | 0xff); + + ex_set_media(); + + CSR_WRITE_2(ELINK_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST); + + CSR_WRITE_4(ELINK_DNLISTPTR, 0); + CSR_WRITE_2(ELINK_COMMAND, TX_ENABLE); + + CSR_WRITE_4(ELINK_UPLISTPTR, RECVBUF_PHYS); + CSR_WRITE_2(ELINK_COMMAND, RX_ENABLE); + CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL); + + GO_WINDOW(1); +} + +void +ex_set_media(void) +{ + int config0, config1; + + CSR_WRITE_2(ELINK_W3_MAC_CONTROL, 0); + + if (ether_medium == ETHERMEDIUM_MII) + goto setcfg; + + GO_WINDOW(4); + CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, 0); + CSR_WRITE_2(ELINK_COMMAND, STOP_TRANSCEIVER); + delay(800); + + switch (ether_medium) { + case ETHERMEDIUM_UTP: + CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, + JABBER_GUARD_ENABLE | LINKBEAT_ENABLE); + break; + case ETHERMEDIUM_BNC: + CSR_WRITE_2(ELINK_COMMAND, START_TRANSCEIVER); + delay(800); + break; + case ETHERMEDIUM_AUI: + CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, SQE_ENABLE); + delay(800); + break; + case ETHERMEDIUM_100TX: + CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, LINKBEAT_ENABLE); + break; + } + +setcfg: + GO_WINDOW(3); + + config0 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG); + config1 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2); + + config1 = config1 & ~CONFIG_MEDIAMASK; + config1 |= (mediatab[ether_medium].address_cfg + << CONFIG_MEDIAMASK_SHIFT); + + CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG, config0); + CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG + 2, config1); +} + +static void +ex_probemedia(void) +{ + int i, j; + struct mtabentry *m; + + /* test for presence of connectors */ + GO_WINDOW(3); + i = CSR_READ_1(ELINK_W3_RESET_OPTIONS); + j = (CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2) & CONFIG_MEDIAMASK) + >> CONFIG_MEDIAMASK_SHIFT; + GO_WINDOW(0); + + for (ether_medium = 0, m = mediatab; + ether_medium < sizeof(mediatab) / sizeof(mediatab[0]); + ether_medium++, m++) { + if (j == m->address_cfg) { + if (!(i & m->config_bit)) { + printf("%s not present\n", m->name); + goto bad; + } + printf("using %s\n", m->name); + return; + } + } + printf("unknown connector\n"); +bad: + ether_medium = -1; +} + +int +EtherInit(unsigned char *myadr) +{ + uint32_t pcicsr; + uint16_t val; + volatile struct ex_upd *upd; +#ifndef _STANDALONE + uint32_t id; +#endif + + if (pcicheck()) { + printf("pcicheck failed\n"); + return 0; + } +#ifndef _STANDALONE + pcicfgread(&mytag, 0, &id); +#endif + for (excard = &excards[0]; excard->did != -1; excard++) { +#ifdef _STANDALONE + if (pcifinddev(0x10b7, excard->did, &mytag) == 0) + goto found; +#else + if (id == (0x10b7 | (excard->did << 16))) + goto found; +#endif + } + printf("no ex\n"); + return 0; + +found: + pcicfgread(&mytag, 0x10, &iobase); + iobase &= ~3; + +#ifndef _STANDALONE + dmamem = mapmem(DMABASE, DMASIZE); + if (!dmamem) + return 0; +#endif + + /* enable bus mastering in PCI command register */ + if (pcicfgread(&mytag, 0x04, (int *)&pcicsr) + || pcicfgwrite(&mytag, 0x04, pcicsr | 4)) { + printf("cannot enable DMA\n"); + return 0; + } + + ex_reset(); + + if (excard->mii) + ether_medium = ETHERMEDIUM_MII; + else { + ex_probemedia(); + if (ether_medium < 0) + return 0; + } + + val = ex_read_eeprom(EEPROM_OEM_ADDR0); + myethaddr[0] = val >> 8; + myethaddr[1] = val & 0xff; + val = ex_read_eeprom(EEPROM_OEM_ADDR1); + myethaddr[2] = val >> 8; + myethaddr[3] = val & 0xff; + val = ex_read_eeprom(EEPROM_OEM_ADDR2); + myethaddr[4] = val >> 8; + myethaddr[5] = val & 0xff; + memcpy(myadr, myethaddr, 6); + + upd = RECVBUF_VIRT; + upd->upd_nextptr = RECVBUF_PHYS; + upd->upd_pktstatus = 1500; + upd->upd_frags[0].fr_addr = RECVBUF_PHYS + 100; + upd->upd_frags[0].fr_len = 1500 | EX_FR_LAST; + + ex_init(); + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) + strncpy(bi_netif.ifname, "ex", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_PCI; + bi_netif.addr.tag = mytag; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + + return 1; +} + +void +EtherStop(void) +{ + /* + * Issue software reset + */ + CSR_WRITE_2(ELINK_COMMAND, RX_DISABLE); + CSR_WRITE_2(ELINK_COMMAND, TX_DISABLE); + CSR_WRITE_2(ELINK_COMMAND, STOP_TRANSCEIVER); + CSR_WRITE_2(ELINK_COMMAND, INTR_LATCH); +} + +int +EtherSend(char *pkt, int len) +{ + volatile struct ex_dpd *dpd; + int i; + + dpd = SNDBUF_VIRT; + + dpd->dpd_nextptr = 0; + dpd->dpd_fsh = len; +#ifdef _STANDALONE + dpd->dpd_frags[0].fr_addr = vtophys(pkt); +#else + memcpy(SNDBUF_VIRT + 100, pkt, len); + dpd->dpd_frags[0].fr_addr = SNDBUF_PHYS + 100; +#endif + dpd->dpd_frags[0].fr_len = len | EX_FR_LAST; + + CSR_WRITE_4(ELINK_DNLISTPTR, SNDBUF_PHYS); + CSR_WRITE_2(ELINK_COMMAND, ELINK_DNUNSTALL); + + i = 10000; + while (!(dpd->dpd_fsh & 0x00010000)) { + if (--i < 0) { + printf("3c90xb: send timeout\n"); + return -1; + } + delay(1); + } + + return len; +} + +int +EtherReceive(char *pkt, int maxlen) +{ + volatile struct ex_upd *upd; + int len; + + upd = RECVBUF_VIRT; + + if (!(upd->upd_pktstatus & ~EX_UPD_PKTLENMASK)) + return 0; + + len = upd->upd_pktstatus & EX_UPD_PKTLENMASK; + if (len > maxlen) + len = 0; + else + memcpy(pkt, RECVBUF_VIRT + 100, len); + + upd->upd_pktstatus = 1500; + CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL); + + return len; +} diff --git a/sys/arch/i386/stand/lib/netif/Makefile.inc b/sys/arch/i386/stand/lib/netif/Makefile.inc new file mode 100644 index 000000000..d7f0b351e --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/Makefile.inc @@ -0,0 +1,36 @@ +## $NetBSD: Makefile.inc,v 1.6 2002/02/17 20:03:11 thorpej Exp $ + +SRCS+= netif_small.c + +.if (${USE_NETIF} == "3c509") +SRCS+= 3c509.c elink3.c +.endif + +.if (${USE_NETIF} == "3c590") +SRCS+= 3c590.c elink3.c +.endif + +.if (${USE_NETIF} == "wd80x3") +SRCS+= wd80x3.c dp8390.c +.endif + +.if (${USE_NETIF} == "pcnet_pci") +SRCS+= pcnet_pci.c am7990.c +.endif + +.if (${USE_NETIF} == "pcnet_isapnp") +SRCS+= pcnet_isapnp.c am7990.c +.endif + +.if (${USE_NETIF} == "i82557") +SRCS+= i82557.c +.endif + +.if (${USE_NETIF} == "3c90xb") +SRCS+= 3c90xb.c +.endif + +.if (${USE_NETIF} == "ne2000_isa") +SRCS+= ne.c dp8390.c +CPPFLAGS+= -DSUPPORT_NE2000 +.endif diff --git a/sys/arch/i386/stand/lib/netif/am7990.c b/sys/arch/i386/stand/lib/netif/am7990.c new file mode 100644 index 000000000..9d9eea88c --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/am7990.c @@ -0,0 +1,280 @@ +/* $NetBSD: am7990.c,v 1.7 2008/12/14 18:46:33 christos Exp $ */ + +/* mostly from netbsd:sys/arch/i386/netboot/ne2100.c + memory allocation now 1 chunk, added deallocation + receive function changed - don't use irq + */ + +/* + * source in this file came from + * the Mach ethernet boot written by Leendert van Doorn. + * + * A very simple network driver for NE2100 boards that polls. + * + * Copyright (c) 1992 by Leendert van Doorn + */ + +#include +#include +#include +#include + +#include + +#include "etherdrv.h" +#include "lance.h" + +extern u_char eth_myaddr[6]; + +extern int lance_rap, lance_rdp; + +static void *dmamem; + +#define LA(adr) vtophys(adr) + +/* Lance register offsets */ +#define LA_CSR lance_rdp +#define LA_CSR1 lance_rdp +#define LA_CSR2 lance_rdp +#define LA_CSR3 lance_rdp +#define LA_RAP lance_rap + +/* + * Some driver specific constants. + * Take care when tuning, this program only has 32 Kb + */ +#define LANCEBUFSIZE 1518 /* plus 4 CRC bytes */ +#define MAXLOOP 1000000L /* arbitrary retry limit */ +#define LOG2NRCVRING 2 /* log2(NRCVRING) */ +#define NRCVRING (1 << LOG2NRCVRING) + +static int next_rmd; /* next receive element */ +static initblock_t *initblock; /* initialization block */ +static tmde_t *tmd; /* transmit ring */ +static rmde_t *rmd; /* receive ring */ +static char rbuffer[NRCVRING][LANCEBUFSIZE]; /* receive buffers */ + +/* + * Stop ethernet board + */ +void +am7990_stop(void) +{ + long l; + + /* stop chip and disable DMA access */ + outw(LA_RAP, RDP_CSR0); + outw(LA_CSR, CSR_STOP); + for (l = 0; (inw(LA_CSR) & CSR_STOP) == 0; l++) { + if (l >= MAXLOOP) { + printf("Lance failed to stop\n"); + return; + } + } +} + +/* + * Reset ethernet board + */ +void +am7990_init(void) +{ + long l; + u_long addr; + int i; + + /* initblock, tmd, and rmd should be 8 byte aligned; + sizes of initblock_t and tmde_t are multiples of 8 */ + dmamem = alloc(sizeof(initblock_t) + + sizeof(tmde_t) + NRCVRING * sizeof(rmde_t) + 4); + /* +4 is ok because alloc()'s result is 4-byte aligned! */ + + initblock = (initblock_t *)(((unsigned long)dmamem + 4) & -8); + tmd = (tmde_t *)(initblock + 1); + rmd = (rmde_t *)(tmd + 1); + + /* stop the chip, and make sure it did */ + am7990_stop(); + + /* fill lance initialization block */ + memset(initblock, 0, sizeof(initblock_t)); + + /* set my ethernet address */ + for (i = 0; i < 6; i++) + initblock->ib_padr[i] = eth_myaddr[i]; + + /* receive ring pointer */ + addr = LA(rmd); + initblock->ib_rdralow = (u_short)addr; + initblock->ib_rdrahigh = (u_char)(addr >> 16); + initblock->ib_rlen = LOG2NRCVRING << 5; + + /* transmit ring with one element */ + addr = LA(tmd); + initblock->ib_tdralow = (u_short)addr; + initblock->ib_tdrahigh = (u_char)(addr >> 16); + initblock->ib_tlen = 0 << 5; + + /* setup the receive ring entries */ + for (next_rmd = 0, i = 0; i < NRCVRING; i++) { + addr = LA(&rbuffer[i]); + rmd[i].rmd_ladr = (u_short)addr; + rmd[i].rmd_hadr = (u_char)(addr >> 16); + rmd[i].rmd_mcnt = 0; + rmd[i].rmd_bcnt = -LANCEBUFSIZE; + rmd[i].rmd_flags = RMD_OWN; + } + + /* zero transmit ring */ + memset(tmd, 0, sizeof(tmde_t)); + + /* give lance the init block */ + addr = LA(initblock); + outw(LA_RAP, RDP_CSR1); + outw(LA_CSR1, (u_short)addr); + outw(LA_RAP, RDP_CSR2); + outw(LA_CSR2, (char)(addr >> 16)); + outw(LA_RAP, RDP_CSR3); + outw(LA_CSR3, 0); + + /* and initialize it */ + outw(LA_RAP, RDP_CSR0); + outw(LA_CSR, CSR_INIT|CSR_STRT); + + /* wait for the lance to complete initialization and fire it up */ + for (l = 0; (inw(LA_CSR) & CSR_IDON) == 0; l++) { + if (l >= MAXLOOP) { + printf("Lance failed to initialize\n"); + break; + } + } + for (l = 0; (inw(LA_CSR)&(CSR_TXON|CSR_RXON)) != (CSR_TXON|CSR_RXON); l++) { + if (l >= MAXLOOP) { + printf("Lance not started\n"); + break; + } + } +} + +/* + * Stop ethernet board and free ressources + */ +void +EtherStop(void) +{ + am7990_stop(); + + dealloc(dmamem, sizeof(initblock_t) + + sizeof(tmde_t) + NRCVRING * sizeof(rmde_t) + 4); +} + +/* + * Send an ethernet packet + */ +int +EtherSend(char *pkt, int len) +{ + long l; + u_long addr; + u_short csr; + int savlen = len; + + if (len < 60) + len = 60; + if (len > LANCEBUFSIZE) { + printf("packet too long\n"); + return -1; + } + + /* set up transmit ring element */ + if (tmd->tmd_flags & TMD_OWN) { + printf("lesend: td busy, status=%x\n", tmd->tmd_flags); + return -1; + } + addr = LA(pkt); + if (addr & 1) { + printf("unaligned data\n"); + return -1; + } + tmd->tmd_ladr = (u_short)addr; + tmd->tmd_hadr = (u_char)(addr >> 16); + tmd->tmd_bcnt = -len; + tmd->tmd_err = 0; + tmd->tmd_flags = TMD_OWN|TMD_STP|TMD_ENP; + + /* start transmission */ + outw(LA_CSR, CSR_TDMD); + + /* wait for interrupt and acknowledge it */ + for (l = 0; l < MAXLOOP; l++) { + if ((csr = inw(LA_CSR)) & CSR_TINT) { + outw(LA_CSR, CSR_TINT); +#ifdef LEDEBUG + if (tmd->tmd_flags & (TMD_ONE|TMD_MORE|TMD_ERR|TMD_DEF)) + printf("lesend: status=%x\n", tmd->tmd_flags); +#endif + break; + } + delay(10); /* don't poll too much on PCI, seems + to disturb DMA on poor hardware */ + } + return savlen; +} + +/* + * Poll the LANCE just see if there's an Ethernet packet + * available. If there is, its contents is returned. + */ +int +EtherReceive(char *pkt, int maxlen) +{ + rmde_t *rp; + u_short csr; + int len = 0; + + csr = inw(LA_CSR); + outw(LA_CSR, csr & (CSR_BABL | CSR_MISS | CSR_MERR | CSR_RINT)); + + if ((next_rmd < 0) || (next_rmd >= NRCVRING)) { + printf("next_rmd bad\n"); + return 0; + } + rp = &rmd[next_rmd]; + + if (rp->rmd_flags & RMD_OWN) + return 0; + + if (csr & (CSR_BABL | CSR_CERR | CSR_MISS | CSR_MERR)) + printf("le: csr %x\n", csr); + + if (rp->rmd_flags & (RMD_FRAM | RMD_OFLO | RMD_CRC | RMD_BUFF)) { + printf("le: rmd_flags %x\n", rp->rmd_flags); + goto cleanup; + } + + if (rp->rmd_flags != (RMD_STP|RMD_ENP)) { + printf("le: rmd_flags %x\n", rp->rmd_flags); + return -1; + } + + len = rp->rmd_mcnt - 4; + + if ((len < 0) || (len >= LANCEBUFSIZE)) { + printf("bad pkt len\n"); + return -1; + } + + if (len <= maxlen) + memcpy(pkt, rbuffer[next_rmd], len); + else + len = 0; + + cleanup: + /* give packet back to the lance */ + rp->rmd_bcnt = -LANCEBUFSIZE; + rp->rmd_mcnt = 0; + rp->rmd_flags = RMD_OWN; + next_rmd = (next_rmd + 1) & (NRCVRING - 1); + + return len; +} diff --git a/sys/arch/i386/stand/lib/netif/dp8390.c b/sys/arch/i386/stand/lib/netif/dp8390.c new file mode 100644 index 000000000..754abb6ea --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/dp8390.c @@ -0,0 +1,362 @@ +/* $NetBSD: dp8390.c,v 1.6 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Polling driver for National Semiconductor DS8390/WD83C690 based + * ethernet adapters. + * + * Copyright (c) 1998 Matthias Drochner. All rights reserved. + * + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * + * Copyright (C) 1993, David Greenman. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided that + * the above copyright and these terms are retained. Under no circumstances is + * the author responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its use. + */ + +#include +#include + +#include +#include + +#include +#include "dp8390.h" +#ifdef SUPPORT_NE2000 +#include "ne.h" +#endif + +#include "etherdrv.h" + +int dp8390_iobase, dp8390_membase, dp8390_memsize; +#if defined(SUPPORT_WD80X3) && defined(SUPPORT_SMC_ULTRA) +int dp8390_is790; +#endif +uint8_t dp8390_cr_proto; +uint8_t dp8390_dcr_reg; + +#define WE_IOBASE dp8390_iobase + +static u_short rec_page_start; +static u_short rec_page_stop; +static u_short next_packet; + +extern u_char eth_myaddr[6]; + +#ifndef _STANDALONE +static void *vmembase; +extern void *mapmem(int, int); +extern void unmapmem(void *, int); +extern int mapio(void); + +static void +bbcopy(void *src, void *dst, int len) +{ + char *s = (char *)src; + char *d = (char *)dst; + + while (len--) + *d++ = *s++; +} +#endif + +static void dp8390_read(int, char *, u_short); + +#define NIC_GET(reg) inb(WE_IOBASE + reg) +#define NIC_PUT(reg, val) outb(WE_IOBASE + reg, val) + +static void +dp8390_init(void) +{ + int i; + + /* + * Initialize the NIC in the exact order outlined in the NS manual. + * This init procedure is "mandatory"...don't change what or when + * things happen. + */ + + /* Set interface for page 0, remote DMA complete, stopped. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); + + if (dp8390_dcr_reg & ED_DCR_LS) { + NIC_PUT(ED_P0_DCR, dp8390_dcr_reg); + } else { + /* + * Set FIFO threshold to 8, No auto-init Remote DMA, byte + * order=80x86, byte-wide DMA xfers, + */ + NIC_PUT(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); + } + + /* Clear remote byte count registers. */ + NIC_PUT(ED_P0_RBCR0, 0); + NIC_PUT(ED_P0_RBCR1, 0); + + /* Tell RCR to do nothing for now. */ + NIC_PUT(ED_P0_RCR, ED_RCR_MON); + + /* Place NIC in internal loopback mode. */ + NIC_PUT(ED_P0_TCR, ED_TCR_LB0); + + /* Set lower bits of byte addressable framing to 0. */ + if (dp8390_is790) + NIC_PUT(0x09, 0); + + /* Initialize receive buffer ring. */ + NIC_PUT(ED_P0_BNRY, rec_page_start); + NIC_PUT(ED_P0_PSTART, rec_page_start); + NIC_PUT(ED_P0_PSTOP, rec_page_stop); + + /* + * Clear all interrupts. A '1' in each bit position clears the + * corresponding flag. + */ + NIC_PUT(ED_P0_ISR, 0xff); + + /* + * Disable all interrupts. + */ + NIC_PUT(ED_P0_IMR, 0); + + /* Program command register for page 1. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STP); + + /* Copy out our station address. */ + for (i = 0; i < 6; ++i) + NIC_PUT(ED_P1_PAR0 + i, eth_myaddr[i]); + + /* + * Set current page pointer to one page after the boundary pointer, as + * recommended in the National manual. + */ + next_packet = rec_page_start + 1; + NIC_PUT(ED_P1_CURR, next_packet); + + /* Program command register for page 0. */ + NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); + + /* directed and broadcast */ + NIC_PUT(ED_P0_RCR, ED_RCR_AB); + + /* Take interface out of loopback. */ + NIC_PUT(ED_P0_TCR, 0); + + /* Fire up the interface. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA); +} + +int +dp8390_config(void) +{ +#ifndef _STANDALONE + if (mapio()) { + printf("no IO access\n"); + return -1; + } + vmembase = mapmem(dp8390_membase, dp8390_memsize); + if (!vmembase) { + printf("no memory access\n"); + return -1; + } +#endif + + rec_page_start = TX_PAGE_START + ED_TXBUF_SIZE; + rec_page_stop = TX_PAGE_START + (dp8390_memsize >> ED_PAGE_SHIFT); + + dp8390_init(); + + return 0; +} + +void +dp8390_stop(void) +{ + int n = 5000; + + /* Stop everything on the interface, and select page 0 registers. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); + + /* + * Wait for interface to enter stopped state, but limit # of checks to + * 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but + * just in case it's an old one. + */ + while (((NIC_GET(ED_P0_ISR) & ED_ISR_RST) == 0) && --n) + continue; + +#ifndef _STANDALONE + unmapmem(vmembase, dp8390_memsize); +#endif +} + +int +EtherSend(char *pkt, int len) +{ +#ifdef SUPPORT_NE2000 + ne2000_writemem(pkt, dp8390_membase, len); +#else +#ifdef _STANDALONE + vpbcopy(pkt, (void *)dp8390_membase, len); +#else + bbcopy(pkt, vmembase, len); +#endif +#endif + + /* Set TX buffer start page. */ + NIC_PUT(ED_P0_TPSR, TX_PAGE_START); + + /* Set TX length. */ + NIC_PUT(ED_P0_TBCR0, len < 60 ? 60 : len); + NIC_PUT(ED_P0_TBCR1, len >> 8); + + /* Set page 0, remote DMA complete, transmit packet, and *start*. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA); + + return len; +} + +static void +dp8390_read(int buf, char *dest, u_short len) +{ + u_short tmp_amount; + + /* Does copy wrap to lower addr in ring buffer? */ + if (buf + len > dp8390_membase + dp8390_memsize) { + tmp_amount = dp8390_membase + dp8390_memsize - buf; + + /* Copy amount up to end of NIC memory. */ +#ifdef SUPPORT_NE2000 + ne2000_readmem(buf, dest, tmp_amount); +#else +#ifdef _STANDALONE + pvbcopy((void *)buf, dest, tmp_amount); +#else + bbcopy(vmembase + buf - dp8390_membase, dest, tmp_amount); +#endif +#endif + + len -= tmp_amount; + buf = RX_BUFBASE + (rec_page_start << ED_PAGE_SHIFT); + dest += tmp_amount; + } +#ifdef SUPPORT_NE2000 + ne2000_readmem(buf, dest, len); +#else +#ifdef _STANDALONE + pvbcopy((void *)buf, dest, len); +#else + bbcopy(vmembase + buf - dp8390_membase, dest, len); +#endif +#endif +} + +int +EtherReceive(char *pkt, int maxlen) +{ + struct dp8390_ring packet_hdr; + int packet_ptr; + u_short len; + u_char boundary, current; +#ifdef DP8390_OLDCHIPS + u_char nlen; +#endif + + if (!(NIC_GET(ED_P0_RSR) & ED_RSR_PRX)) + return 0; /* XXX error handling */ + + /* Set NIC to page 1 registers to get 'current' pointer. */ + NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STA); + + /* + * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e. + * it points to where new data has been buffered. The 'CURR' (current) + * register points to the logical end of the ring-buffer - i.e. it + * points to where additional new data will be added. We loop here + * until the logical beginning equals the logical end (or in other + * words, until the ring-buffer is empty). + */ + current = NIC_GET(ED_P1_CURR); + + /* Set NIC to page 0 registers to update boundary register. */ + NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA); + + if (next_packet == current) + return 0; + + /* Get pointer to this buffer's header structure. */ + packet_ptr = RX_BUFBASE + (next_packet << ED_PAGE_SHIFT); + + /* + * The byte count includes a 4 byte header that was added by + * the NIC. + */ +#ifdef SUPPORT_NE2000 + ne2000_readmem(packet_ptr, (void *)&packet_hdr, 4); +#else +#ifdef _STANDALONE + pvbcopy((void *)packet_ptr, &packet_hdr, 4); +#else + bbcopy(vmembase + packet_ptr - dp8390_membase, &packet_hdr, 4); +#endif +#endif + + len = packet_hdr.count; + +#ifdef DP8390_OLDCHIPS + /* + * Try do deal with old, buggy chips that sometimes duplicate + * the low byte of the length into the high byte. We do this + * by simply ignoring the high byte of the length and always + * recalculating it. + * + * NOTE: sc->next_packet is pointing at the current packet. + */ + if (packet_hdr.next_packet >= next_packet) + nlen = (packet_hdr.next_packet - next_packet); + else + nlen = ((packet_hdr.next_packet - rec_page_start) + + (rec_page_stop - next_packet)); + --nlen; + if ((len & ED_PAGE_MASK) + sizeof(packet_hdr) > ED_PAGE_SIZE) + --nlen; + len = (len & ED_PAGE_MASK) | (nlen << ED_PAGE_SHIFT); +#ifdef DIAGNOSTIC + if (len != packet_hdr.count) { + printf(IFNAME ": length does not match next packet pointer\n"); + printf(IFNAME ": len %04x nlen %04x start %02x " + "first %02x curr %02x next %02x stop %02x\n", + packet_hdr.count, len, + rec_page_start, next_packet, current, + packet_hdr.next_packet, rec_page_stop); + } +#endif +#endif + + if (packet_hdr.next_packet < rec_page_start || + packet_hdr.next_packet >= rec_page_stop) + panic(IFNAME ": RAM corrupt"); + + len -= sizeof(struct dp8390_ring); + if (len < maxlen) { + /* Go get packet. */ + dp8390_read(packet_ptr + sizeof(struct dp8390_ring), + pkt, len); + } else + len = 0; + + /* Update next packet pointer. */ + next_packet = packet_hdr.next_packet; + + /* + * Update NIC boundary pointer - being careful to keep it one + * buffer behind (as recommended by NS databook). + */ + boundary = next_packet - 1; + if (boundary < rec_page_start) + boundary = rec_page_stop - 1; + NIC_PUT(ED_P0_BNRY, boundary); + + return len; +} diff --git a/sys/arch/i386/stand/lib/netif/dp8390.h b/sys/arch/i386/stand/lib/netif/dp8390.h new file mode 100644 index 000000000..c1d40948b --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/dp8390.h @@ -0,0 +1,33 @@ +/* $NetBSD: dp8390.h,v 1.6 2008/12/14 18:46:33 christos Exp $ */ + +extern int dp8390_config(void); +extern void dp8390_stop(void); + +extern int dp8390_iobase; +extern int dp8390_membase; +extern int dp8390_memsize; +#ifdef SUPPORT_WD80X3 +#ifdef SUPPORT_SMC_ULTRA +extern int dp8390_is790; +#else +#define dp8390_is790 0 +#endif +#else +#ifdef SUPPORT_SMC_ULTRA +#define dp8390_is790 1 +#endif +#endif + +#ifdef SUPPORT_NE2000 +#define dp8390_is790 0 +#define IFNAME "ne" +#define RX_BUFBASE 0 +#define TX_PAGE_START (dp8390_membase >> ED_PAGE_SHIFT) +#else +#define IFNAME "we" +#define RX_BUFBASE dp8390_membase +#define TX_PAGE_START 0 +#endif + +extern uint8_t dp8390_cr_proto; /* values always set in CR */ +extern uint8_t dp8390_dcr_reg; /* override DCR if LS is set */ diff --git a/sys/arch/i386/stand/lib/netif/elink3.c b/sys/arch/i386/stand/lib/netif/elink3.c new file mode 100644 index 000000000..1a115d47d --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/elink3.c @@ -0,0 +1,336 @@ +/* $NetBSD: elink3.c,v 1.4 2008/12/14 18:46:33 christos Exp $ */ + +/* stripped down from freebsd:sys/i386/netboot/3c509.c */ + +/************************************************************************** +NETBOOT - BOOTP/TFTP Bootstrap Program + +Author: Martin Renters. + Date: Mar 22 1995 + + This code is based heavily on David Greenman's if_ed.c driver and + Andres Vega Garcia's if_ep.c driver. + + Copyright (C) 1993-1994, David Greenman, Martin Renters. + Copyright (C) 1993-1995, Andres Vega Garcia. + Copyright (C) 1995, Serge Babkin. + This software may be used, modified, copied, distributed, and sold, in + both source and binary form provided that the above copyright and these + terms are retained. Under no circumstances are the authors responsible for + the proper functioning of this software, nor do the authors assume any + responsibility for damages incurred with its use. + +3c509 support added by Serge Babkin (babkin@hq.icb.chel.su) + +3c509.c,v 1.2 1995/05/30 07:58:52 rgrimes Exp + +***************************************************************************/ + +#include +#include + +#include + +#include + +#include "etherdrv.h" +#include "3c509.h" + +extern unsigned short eth_base; + +extern u_char eth_myaddr[6]; + +void +epstop(void) +{ + + /* stop card */ + outw(BASE + EP_COMMAND, RX_DISABLE); + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); + + outw(BASE + EP_COMMAND, TX_DISABLE); + outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); + + outw(BASE + EP_COMMAND, RX_RESET); + outw(BASE + EP_COMMAND, TX_RESET); + + outw(BASE + EP_COMMAND, C_INTR_LATCH); + outw(BASE + EP_COMMAND, SET_RD_0_MASK); + outw(BASE + EP_COMMAND, SET_INTR_MASK); + outw(BASE + EP_COMMAND, SET_RX_FILTER); +} + +void +EtherStop(void) +{ + + epstop(); + outw(BASE + EP_COMMAND, GLOBAL_RESET); + delay(100000); +} + +/************************************************************************** +ETH_RESET - Reset adapter +***************************************************************************/ +void +epreset(void) +{ + int i; + + /*********************************************************** + Reset 3Com 509 card + *************************************************************/ + + epstop(); + + /* + * initialize card + */ + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) + continue; + + GO_WINDOW(0); + + /* Disable the card */ + outw(BASE + EP_W0_CONFIG_CTRL, 0); + + /* Configure IRQ to none */ + outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0)); + + /* Enable the card */ + outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); + + GO_WINDOW(2); + + /* Reload the ether_addr. */ + for (i = 0; i < 6; i++) + outb(BASE + EP_W2_ADDR_0 + i, eth_myaddr[i]); + + outw(BASE + EP_COMMAND, RX_RESET); + outw(BASE + EP_COMMAND, TX_RESET); + + /* Window 1 is operating window */ + GO_WINDOW(1); + for (i = 0; i < 31; i++) + inb(BASE + EP_W1_TX_STATUS); + + /* get rid of stray intr's */ + outw(BASE + EP_COMMAND, ACK_INTR | 0xff); + + outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS); + + outw(BASE + EP_COMMAND, SET_INTR_MASK); + + outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | + FIL_BRDCST); + + /* configure BNC */ + if (ether_medium == ETHERMEDIUM_BNC) { + outw(BASE + EP_COMMAND, START_TRANSCEIVER); + delay(1000); + } + /* configure UTP */ + if (ether_medium == ETHERMEDIUM_UTP) { + GO_WINDOW(4); + outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); + GO_WINDOW(1); + } + + /* start tranciever and receiver */ + outw(BASE + EP_COMMAND, RX_ENABLE); + outw(BASE + EP_COMMAND, TX_ENABLE); + + /* set early threshold for minimal packet length */ + outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | 64); + + outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16); +} + +/************************************************************************** +ETH_TRANSMIT - Transmit a frame +***************************************************************************/ +static const char padmap[] = { + 0, 3, 2, 1}; + +int +EtherSend(char *pkt, int len) +{ + int pad; + int status; + +#ifdef EDEBUG + printf("{l=%d}", len); +#endif + + pad = padmap[len & 3]; + + /* + * The 3c509 automatically pads short packets to minimum ethernet length, + * but we drop packets that are too large. Perhaps we should truncate + * them instead? + */ + if (len + pad > ETHER_MAX_LEN) { + return -1; + } + + /* drop acknowledgements */ + while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE ) { + if (status & (TXS_UNDERRUN | TXS_MAX_COLLISION | + TXS_STATUS_OVERFLOW)) { + outw(BASE + EP_COMMAND, TX_RESET); + outw(BASE + EP_COMMAND, TX_ENABLE); + } + + outb(BASE + EP_W1_TX_STATUS, 0x0); + } + + while (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) { + /* no room in FIFO */ + continue; + } + + outw(BASE + EP_W1_TX_PIO_WR_1, len); + outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */ + + /* write packet */ + outsw(BASE + EP_W1_TX_PIO_WR_1, pkt, len / 2); + if (len & 1) + outb(BASE + EP_W1_TX_PIO_WR_1, *(pkt + len - 1)); + + while (pad--) + outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */ + + /* timeout after sending */ + delay(1000); + return len; +} + +/************************************************************************** +ETH_POLL - Wait for a frame +***************************************************************************/ +int +EtherReceive(char *pkt, int maxlen) +{ + /* common variables */ + int len; + /* variables for 3C509 */ + short status, cst; + register short rx_fifo; + + cst = inw(BASE + EP_STATUS); + +#ifdef EDEBUG + if (cst & 0x1FFF) + printf("-%x-",cst); +#endif + + if ((cst & (S_RX_COMPLETE|S_RX_EARLY)) == 0) { + /* acknowledge everything */ + outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS)); + outw(BASE + EP_COMMAND, C_INTR_LATCH); + + return 0; + } + + status = inw(BASE + EP_W1_RX_STATUS); +#ifdef EDEBUG + printf("*%x*",status); +#endif + + if (status & ERR_RX) { + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + return 0; + } + + rx_fifo = status & RX_BYTES_MASK; + if (rx_fifo == 0) + return 0; + + if (rx_fifo > maxlen) + goto zulang; + + /* read packet */ +#ifdef EDEBUG + printf("[l=%d",rx_fifo); +#endif + insw(BASE + EP_W1_RX_PIO_RD_1, pkt, rx_fifo / 2); + if (rx_fifo & 1) + pkt[rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1); + len = rx_fifo; + + for (;;) { + status = inw(BASE + EP_W1_RX_STATUS); +#ifdef EDEBUG + printf("*%x*",status); +#endif + rx_fifo = status & RX_BYTES_MASK; + + if (rx_fifo > 0) { + if ((len + rx_fifo) > maxlen) + goto zulang; + + insw(BASE + EP_W1_RX_PIO_RD_1, pkt + len, rx_fifo / 2); + if (rx_fifo & 1) + pkt[len + rx_fifo-1] = inb(BASE + EP_W1_RX_PIO_RD_1); + len += rx_fifo; +#ifdef EDEBUG + printf("+%d",rx_fifo); +#endif + } + + if ((status & RX_INCOMPLETE) == 0) { +#ifdef EDEBUG + printf("=%d",len); +#endif + break; + } + + delay(1000); + } + + /* acknowledge reception of packet */ + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) + continue; + + return len; + + zulang: + outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); + while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) + continue; + return 0; +} + +/************************************************************************* + 3Com 509 - specific routines +**************************************************************************/ + +static int +eeprom_rdy(void) +{ + int i; + + for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++); + if (i >= MAX_EEPROMBUSY) { + printf("3c509: eeprom failed to come ready.\r\n"); + return 0; + } + return 1; +} + +/* + * get_e: gets a 16 bits word from the EEPROM. we must have set the window + * before + */ +int +ep_get_e(int offset) +{ + if (!eeprom_rdy()) + return 0xffff; + outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset); + if (!eeprom_rdy()) + return 0xffff; + return inw(IS_BASE + EP_W0_EEPROM_DATA); +} diff --git a/sys/arch/i386/stand/lib/netif/etherdrv.h b/sys/arch/i386/stand/lib/netif/etherdrv.h new file mode 100644 index 000000000..4ef2394c5 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/etherdrv.h @@ -0,0 +1,39 @@ +/* $NetBSD: etherdrv.h,v 1.9 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +int EtherInit(unsigned char *); +int EtherSend(char *, int); +int EtherReceive(char *, int); +void EtherStop(void); + +extern unsigned ether_medium; +#define ETHERMEDIUM_BNC 0 +#define ETHERMEDIUM_UTP 1 +#define ETHERMEDIUM_AUI 2 +#define ETHERMEDIUM_MII 3 +#define ETHERMEDIUM_100TX 4 diff --git a/sys/arch/i386/stand/lib/netif/i82557.c b/sys/arch/i386/stand/lib/netif/i82557.c new file mode 100644 index 000000000..6579c974d --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/i82557.c @@ -0,0 +1,492 @@ +/* $NetBSD: i82557.c,v 1.11 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1998, 1999 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1995, David Greenman + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include + +#include + +#include +#include + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +#include +#include +#endif + +#include "etherdrv.h" + +#define RECVBUF_SIZE 1600 /* struct fxp_rfa + packet */ + +#ifdef _STANDALONE +static pcihdl_t mytag; +static char recvbuf[RECVBUF_SIZE]; +#define RECVBUF_PHYS vtophys(recvbuf) +#define RECVBUF_VIRT ((void *)recvbuf) +static union _sndbuf { + struct fxp_cb_config cbp; + struct fxp_cb_ias cb_ias; + struct fxp_cb_tx txp; +} sndbuf; +#define SNDBUF_PHYS vtophys(&sndbuf) +#define SNDBUF_VIRT ((void *)&sndbuf) +#else /* !standalone, userspace testing environment */ +#define PCI_MODE1_ENABLE 0x80000000UL +static pcihdl_t mytag = PCI_MODE1_ENABLE | (PCIDEVNO << 11); + +extern void *mapmem(int, int); +void *dmamem; /* virtual */ +#define RECVBUF_PHYS DMABASE +#define RECVBUF_VIRT dmamem +#define SNDBUF_PHYS (DMABASE + RECVBUF_SIZE) +#define SNDBUF_VIRT ((void *)(((char *)dmamem) + RECVBUF_SIZE)) +#endif /* _STANDALONE */ + +static void fxp_read_eeprom(uint16_t *, int, int); +static inline void fxp_scb_wait(void); +#ifdef DEBUG +static void fxp_checkintr(char *); +#else +#define fxp_checkintr(x) +#endif +static void fxp_startreceiver(void); + +/* + * Template for default configuration parameters. + * See struct fxp_cb_config for the bit definitions. + */ +static uint8_t fxp_cb_config_template[] = { + 0x0, 0x0, /* cb_status */ + 0x80, 0x2, /* cb_command */ + 0xff, 0xff, 0xff, 0xff, /* link_addr */ + 0x16, /* 0 */ + 0x8, /* 1 */ + 0x0, /* 2 */ + 0x0, /* 3 */ + 0x0, /* 4 */ + 0x80, /* 5 */ + 0xb2, /* 6 */ + 0x3, /* 7 */ + 0x1, /* 8 */ + 0x0, /* 9 */ + 0x26, /* 10 */ + 0x0, /* 11 */ + 0x60, /* 12 */ + 0x0, /* 13 */ + 0xf2, /* 14 */ + 0x48, /* 15 */ + 0x0, /* 16 */ + 0x40, /* 17 */ + 0xf3, /* 18 */ + 0x0, /* 19 */ + 0x3f, /* 20 */ + 0x5 /* 21 */ +}; + +static int tx_threshold = 64; /* x8, max 192 */ + +#define CSR_READ_1(reg) inb(iobase + (reg)) +#define CSR_READ_2(reg) inw(iobase + (reg)) +#define CSR_WRITE_1(reg, val) outb(iobase + (reg), val) +#define CSR_WRITE_2(reg, val) outw(iobase + (reg), val) +#define CSR_WRITE_4(reg, val) outl(iobase + (reg), val) +#define DELAY(n) delay(n) + +static int iobase; + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) +static struct btinfo_netif bi_netif; +#endif + +/* + * Wait for the previous command to be accepted (but not necessarily + * completed). + */ +static inline void +fxp_scb_wait(void) +{ + int i = 10000; + + while (CSR_READ_1(FXP_CSR_SCB_COMMAND) && --i) + DELAY(1); + if (i == 0) + printf("fxp: WARNING: SCB timed out!\n"); +} + +#ifdef DEBUG +static void +fxp_checkintr(char *msg) +{ + uint8_t statack; + int i = 10000; + + do { + statack = CSR_READ_1(FXP_CSR_SCB_STATACK); + } while ((statack == 0) && (--i > 0)); + + if (statack != 0) { + CSR_WRITE_1(FXP_CSR_SCB_STATACK, statack); + printf("%s: ack'd irq %x, i=%d\n", msg, statack, i); + } +} +#endif + +int +EtherInit(unsigned char *myadr) +{ +#ifndef _STANDALONE + uint32_t id; +#endif + volatile struct fxp_cb_config *cbp; + volatile struct fxp_cb_ias *cb_ias; + int i; + + if (pcicheck()) { + printf("pcicheck failed\n"); + return 0; + } +#ifdef _STANDALONE + if (pcifinddev(0x8086, 0x1229, &mytag)) { + printf("no fxp\n"); + return 0; + } +#else + pcicfgread(&mytag, 0, &id); + if (id != 0x12298086) { + printf("no fxp\n"); + return 0; + } +#endif + + pcicfgread(&mytag, FXP_PCI_IOBA, &iobase); + iobase &= ~3; + +#ifndef _STANDALONE + dmamem = mapmem(DMABASE, DMASIZE); + if (!dmamem) + return 0; +#endif + + fxp_read_eeprom((void *)myadr, 0, 3); + + /* + * Initialize base of CBL and RFA memory. Loading with zero + * sets it up for regular linear addressing. + */ + CSR_WRITE_4(FXP_CSR_SCB_GENERAL, 0); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE); + + fxp_scb_wait(); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE); + + cbp = SNDBUF_VIRT; + /* + * This memcpy is kind of disgusting, but there are a bunch of must be + * zero and must be one bits in this structure and this is the easiest + * way to initialize them all to proper values. + */ + memcpy((void *)cbp, fxp_cb_config_template, + sizeof(fxp_cb_config_template)); + +#define prm 0 +#define phy_10Mbps_only 0 +#define all_mcasts 0 + cbp->cb_status = 0; + cbp->cb_command = FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL; + cbp->link_addr = -1; /* (no) next command */ + cbp->byte_count = 22; /* (22) bytes to config */ + cbp->rx_fifo_limit = 8; /* rx fifo threshold (32 bytes) */ + cbp->tx_fifo_limit = 0; /* tx fifo threshold (0 bytes) */ + cbp->adaptive_ifs = 0; /* (no) adaptive interframe spacing */ + cbp->rx_dma_bytecount = 0; /* (no) rx DMA max */ + cbp->tx_dma_bytecount = 0; /* (no) tx DMA max */ + cbp->dma_mbce = 0; /* (disable) dma max counters */ + cbp->late_scb = 0; /* (don't) defer SCB update */ + cbp->tno_int_or_tco_en = 0; /* (disable) tx not okay interrupt */ + cbp->ci_int = 0; /* interrupt on CU not active */ + cbp->save_bf = prm; /* save bad frames */ + cbp->disc_short_rx = !prm; /* discard short packets */ + cbp->underrun_retry = 1; /* retry mode (1) on DMA underrun */ + cbp->mediatype = !phy_10Mbps_only; /* interface mode */ + cbp->nsai = 1; /* (don't) disable source addr insert */ + cbp->preamble_length = 2; /* (7 byte) preamble */ + cbp->loopback = 0; /* (don't) loopback */ + cbp->linear_priority = 0; /* (normal CSMA/CD operation) */ + cbp->linear_pri_mode = 0; /* (wait after xmit only) */ + cbp->interfrm_spacing = 6; /* (96 bits of) interframe spacing */ + cbp->promiscuous = prm; /* promiscuous mode */ + cbp->bcast_disable = 0; /* (don't) disable broadcasts */ + cbp->crscdt = 0; /* (CRS only) */ + cbp->stripping = !prm; /* truncate rx packet to byte count */ + cbp->padding = 1; /* (do) pad short tx packets */ + cbp->rcv_crc_xfer = 0; /* (don't) xfer CRC to host */ + cbp->force_fdx = 0; /* (don't) force full duplex */ + cbp->fdx_pin_en = 1; /* (enable) FDX# pin */ + cbp->multi_ia = 0; /* (don't) accept multiple IAs */ + cbp->mc_all = all_mcasts;/* accept all multicasts */ +#undef prm +#undef phy_10Mbps_only +#undef all_mcasts + + /* + * Start the config command/DMA. + */ + fxp_scb_wait(); + CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); + /* ...and wait for it to complete. */ + i = 10000; + while (!(cbp->cb_status & FXP_CB_STATUS_C) && (--i > 0)) + DELAY(1); + if (i == 0) + printf("config timeout"); + + fxp_checkintr("config"); + + cb_ias = SNDBUF_VIRT; + /* + * Now initialize the station address. Temporarily use the TxCB + * memory area like we did above for the config CB. + */ + cb_ias->cb_status = 0; + cb_ias->cb_command = FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL; + cb_ias->link_addr = -1; + memcpy((void *)cb_ias->macaddr, myadr, 6); + + /* + * Start the IAS (Individual Address Setup) command/DMA. + */ + fxp_scb_wait(); + /* address is still there */ + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); + /* ...and wait for it to complete. */ + i = 10000; + while (!(cb_ias->cb_status & FXP_CB_STATUS_C) && (--i > 0)) + DELAY(1); + if (i == 0) + printf("ias timeout"); + + fxp_checkintr("ias"); + + fxp_startreceiver(); + +#if defined(_STANDALONE) && !defined(SUPPORT_NO_NETBSD) + strncpy(bi_netif.ifname, "fxp", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_PCI; + bi_netif.addr.tag = mytag; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + + return 1; +} + +void +EtherStop(void) +{ + + /* + * Issue software reset + */ + CSR_WRITE_4(FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); + DELAY(10); +} + +int +EtherSend(char *pkt, int len) +{ + volatile struct fxp_cb_tx *txp; +#ifdef _STANDALONE + static volatile struct fxp_tbd tbd; +#endif + volatile struct fxp_tbd *tbdp; + int i; + + txp = SNDBUF_VIRT; +#ifdef _STANDALONE + tbdp = &tbd; + txp->tbd_array_addr = vtophys((void *)&tbd); + tbdp->tb_addr = vtophys(pkt); +#else + /* XXX assuming we send at max 400 bytes */ + tbdp = (struct fxp_tbd *)(SNDBUF_VIRT + 440); + txp->tbd_array_addr = SNDBUF_PHYS + 440; + memcpy(SNDBUF_VIRT + 400, pkt, len); + tbdp->tb_addr = SNDBUF_PHYS + 400; +#endif + tbdp->tb_size = len; + txp->tbd_number = 1; + txp->cb_status = 0; + txp->cb_command = + FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_EL; + txp->tx_threshold = tx_threshold; + + txp->link_addr = -1; + txp->byte_count = 0; + + fxp_scb_wait(); + CSR_WRITE_4(FXP_CSR_SCB_GENERAL, SNDBUF_PHYS); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); + /* ...and wait for it to complete. */ + i = 10000; + while (!(txp->cb_status & FXP_CB_STATUS_C) && (--i > 0)) + DELAY(1); + if (i == 0) + printf("send timeout"); + + fxp_checkintr("send"); + + return len; +} + +static void +fxp_startreceiver(void) +{ + volatile struct fxp_rfa *rfa; + uint32_t v; + + rfa = RECVBUF_VIRT; + rfa->size = RECVBUF_SIZE - sizeof(struct fxp_rfa); + rfa->rfa_status = 0; + rfa->rfa_control = FXP_RFA_CONTROL_S; + rfa->actual_size = 0; + v = RECVBUF_PHYS; /* close the "ring" */ + memcpy((void *)&rfa->link_addr, &v, sizeof(v)); + v = -1; + memcpy((void *)&rfa->rbd_addr, &v, sizeof(v)); + + fxp_scb_wait(); + CSR_WRITE_4(FXP_CSR_SCB_GENERAL, RECVBUF_PHYS); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START); +} + +int +EtherReceive(char *pkt, int maxlen) +{ + uint8_t ruscus; + volatile struct fxp_rfa *rfa; + int len = 0; + + ruscus = CSR_READ_1(FXP_CSR_SCB_RUSCUS); + if (((ruscus >> 2) & 0x0f) == FXP_SCB_RUS_READY) + return 0; + if (((ruscus >> 2) & 0x0f) != FXP_SCB_RUS_SUSPENDED) { + printf("rcv: ruscus=%x\n", ruscus); + return 0; + } + + rfa = RECVBUF_VIRT; + if (rfa->rfa_status & FXP_RFA_STATUS_C) { + len = rfa->actual_size & 0x7ff; + if (len <= maxlen) { + memcpy(pkt, (char *) rfa + RFA_SIZE, maxlen); +#if 0 + printf("rfa status=%x, len=%x\n", + rfa->rfa_status, len); +#endif + } else + len = 0; + } + + fxp_scb_wait(); + CSR_WRITE_1(FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_RESUME); + + return len; +} + +/* + * Read from the serial EEPROM. Basically, you manually shift in + * the read opcode (one bit at a time) and then shift in the address, + * and then you shift out the data (all of this one bit at a time). + * The word size is 16 bits, so you have to provide the address for + * every 16 bits of data. + */ +static void +fxp_read_eeprom(uint16_t *data, int offset, int words) +{ + uint16_t reg; + int i, x; + + for (i = 0; i < words; i++) { + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, FXP_EEPROM_EECS); + /* + * Shift in read opcode. + */ + for (x = 3; x > 0; x--) { + if (FXP_EEPROM_OPC_READ & (1 << (x - 1))) { + reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; + } else { + reg = FXP_EEPROM_EECS; + } + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg); + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, + reg | FXP_EEPROM_EESK); + DELAY(1); + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg); + DELAY(1); + } + /* + * Shift in address. + */ + for (x = 6; x > 0; x--) { + if ((i + offset) & (1 << (x - 1))) { + reg = FXP_EEPROM_EECS | FXP_EEPROM_EEDI; + } else { + reg = FXP_EEPROM_EECS; + } + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg); + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, + reg | FXP_EEPROM_EESK); + DELAY(1); + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg); + DELAY(1); + } + reg = FXP_EEPROM_EECS; + data[i] = 0; + /* + * Shift out data. + */ + for (x = 16; x > 0; x--) { + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, + reg | FXP_EEPROM_EESK); + DELAY(1); + if (CSR_READ_2(FXP_CSR_EEPROMCONTROL) & + FXP_EEPROM_EEDO) + data[i] |= (1 << (x - 1)); + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, reg); + DELAY(1); + } + CSR_WRITE_2(FXP_CSR_EEPROMCONTROL, 0); + DELAY(1); + } +} diff --git a/sys/arch/i386/stand/lib/netif/lance.h b/sys/arch/i386/stand/lib/netif/lance.h new file mode 100644 index 000000000..f71dd14e1 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/lance.h @@ -0,0 +1,113 @@ +/* $NetBSD: lance.h,v 1.2 2008/12/14 18:46:33 christos Exp $ */ + +/* + * source in this file came from + * the Mach ethernet boot written by Leendert van Doorn. + */ + +/* RAP functions as a select for RDP */ +#define RDP_CSR0 0 +#define RDP_CSR1 1 +#define RDP_CSR2 2 +#define RDP_CSR3 3 + +/* contents of csr0 */ +#define CSR_ERR 0x8000 +#define CSR_BABL 0x4000 +#define CSR_CERR 0x2000 +#define CSR_MISS 0x1000 +#define CSR_MERR 0x0800 +#define CSR_RINT 0x0400 +#define CSR_TINT 0x0200 +#define CSR_IDON 0x0100 +#define CSR_INTR 0x0080 +#define CSR_INEA 0x0040 +#define CSR_RXON 0x0020 +#define CSR_TXON 0x0010 +#define CSR_TDMD 0x0008 +#define CSR_STOP 0x0004 +#define CSR_STRT 0x0002 +#define CSR_INIT 0x0001 + +/* csr1 contains low 16 bits of address of Initialization Block */ + +/* csr2 contains in low byte high 8 bits of address of InitBlock */ + +/* contents of csr3 */ +#define CSR3_BSWP 0x04 /* byte swap (for big endian) */ +#define CSR3_ACON 0x02 /* ALE control */ +#define CSR3_BCON 0x01 /* byte control */ + +/* + * The initialization block + */ +typedef struct { + u_short ib_mode; /* modebits, see below */ + char ib_padr[6]; /* physical 48bit Ether-address */ + u_short ib_ladrf[4]; /* 64bit hashtable for "logical" addresses */ + u_short ib_rdralow; /* low 16 bits of Receiver Descr. Ring addr */ + u_char ib_rdrahigh; /* high 8 bits of Receiver Descr. Ring addr */ + u_char ib_rlen; /* upper 3 bits are 2log Rec. Ring Length */ + u_short ib_tdralow; /* low 16 bits of Transm. Descr. Ring addr */ + u_char ib_tdrahigh; /* high 8 bits of Transm. Descr. Ring addr */ + u_char ib_tlen; /* upper 3 bits are 2log Transm. Ring Length */ +} initblock_t; + +/* bits in mode */ +#define IB_PROM 0x8000 +#define IB_INTL 0x0040 +#define IB_DRTY 0x0020 +#define IB_COLL 0x0010 +#define IB_DTCR 0x0008 +#define IB_LOOP 0x0004 +#define IB_DTX 0x0002 +#define IB_DRX 0x0001 + +/* + * A receive message descriptor entry + */ +typedef struct { + u_short rmd_ladr; /* low 16 bits of bufaddr */ + char rmd_hadr; /* high 8 bits of bufaddr */ + char rmd_flags; /* see below */ + short rmd_bcnt; /* two's complement of buffer byte count */ + u_short rmd_mcnt; /* message byte count */ +} rmde_t; + +/* bits in flags */ +#define RMD_OWN 0x80 +#define RMD_ERR 0x40 +#define RMD_FRAM 0x20 +#define RMD_OFLO 0x10 +#define RMD_CRC 0x08 +#define RMD_BUFF 0x04 +#define RMD_STP 0x02 +#define RMD_ENP 0x01 + +/* + * A transmit message descriptor entry + */ +typedef struct { + u_short tmd_ladr; /* low 16 bits of bufaddr */ + u_char tmd_hadr; /* high 8 bits of bufaddr */ + u_char tmd_flags; /* see below */ + short tmd_bcnt; /* two's complement of buffer byte count */ + u_short tmd_err; /* more error bits + TDR */ +} tmde_t; + +/* bits in flags */ +#define TMD_OWN 0x80 +#define TMD_ERR 0x40 +#define TMD_MORE 0x10 +#define TMD_ONE 0x08 +#define TMD_DEF 0x04 +#define TMD_STP 0x02 +#define TMD_ENP 0x01 + +/* bits in tmd_err */ +#define TMDE_BUFF 0x8000 +#define TMDE_UFLO 0x4000 +#define TMDE_LCOL 0x1000 +#define TMDE_LCAR 0x0800 +#define TMDE_RTRY 0x0400 +#define TMDE_TDR 0x003F /* mask for TDR */ diff --git a/sys/arch/i386/stand/lib/netif/ne.c b/sys/arch/i386/stand/lib/netif/ne.c new file mode 100644 index 000000000..d9fad5c7d --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/ne.c @@ -0,0 +1,274 @@ +/* $NetBSD: ne.c,v 1.7 2008/12/14 18:46:33 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Device driver for National Semiconductor DS8390/WD83C690 based ethernet + * adapters. + * + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * + * Copyright (C) 1993, David Greenman. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided that + * the above copyright and these terms are retained. Under no circumstances is + * the author responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its use. + */ + +/* + * this code is mainly obtained from /sys/dev/ic/ne2000.c . + */ + +#include +#include + +#include +#include + +#ifdef _STANDALONE +#include +#include +#endif + +#include "etherdrv.h" +#include +#include +#include "dp8390.h" +#include "ne.h" + +#ifndef BASEREG +#define BASEREG 0x300 +#endif + +#define NE_BASEREG BASEREG +#define NE_ASIC_BASEREG (NE_BASEREG+NE2000_ASIC_OFFSET) + +#define NIC_PORT(x) (NE_BASEREG + (x)) +#define NIC_INB(x) inb(NIC_PORT(x)) +#define NIC_OUTB(x, b) outb(NIC_PORT(x), (b)) + +#define NE_16BIT + +#define DELAY(x) delay(x) + +#define ASIC_PORT(x) (NE_ASIC_BASEREG + (x)) +#define ASIC_INB(x) inb(ASIC_PORT(x)) +#define ASIC_INW(x) inw(ASIC_PORT(x)) +#define ASIC_OUTB(x, b) outb(ASIC_PORT(x), (b)) +#define ASIC_OUTW(x, b) outw(ASIC_PORT(x), (b)) + +u_char eth_myaddr[6]; + +#ifdef _STANDALONE +static struct btinfo_netif bi_netif; +#endif + +int +EtherInit(unsigned char *myadr) +{ + uint8_t tmp; + int i; + + printf("ne: trying iobase=0x%x\n", NE_BASEREG); + + dp8390_iobase = NE_BASEREG; + dp8390_membase = dp8390_memsize = 8192*2; + dp8390_cr_proto = ED_CR_RD2; + dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS +#ifdef NE_16BIT + | ED_DCR_WTS +#endif + ; + + /* reset */ + tmp = ASIC_INB(NE2000_ASIC_RESET); + DELAY(10000); + ASIC_OUTB(NE2000_ASIC_RESET, tmp); + DELAY(5000); + + NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); + DELAY(5000); + + tmp = NIC_INB(ED_P0_CR); + if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) != + (ED_CR_RD2 | ED_CR_STP)) { + goto out; + } + + tmp = NIC_INB(ED_P0_ISR); + if ((tmp & ED_ISR_RST) != ED_ISR_RST) { + goto out; + } + + NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); + + for (i = 0; i < 100; i++) { + if ((NIC_INB(ED_P0_ISR) & ED_ISR_RST) == + ED_ISR_RST) { + /* Ack the reset bit. */ + NIC_OUTB(ED_P0_ISR, ED_ISR_RST); + break; + } + DELAY(100); + } + + printf("ne: found\n"); + + /* + * This prevents packets from being stored in the NIC memory when + * the readmem routine turns on the start bit in the CR. + */ + NIC_OUTB(ED_P0_RCR, ED_RCR_MON); + + /* Temporarily initialize DCR for byte operations. */ + NIC_OUTB(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); + + NIC_OUTB(ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT); + NIC_OUTB(ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT); + +#ifdef HWADDR + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i] = HWADDR[i]; +#else +{ + uint8_t romdata[16]; + + ne2000_readmem(0, romdata, 16); + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i] = romdata[i*2]; +} +#endif + + if (dp8390_config()) + goto out; + +#ifdef _STANDALONE + strncpy(bi_netif.ifname, "ne", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_ISA; + bi_netif.addr.iobase = NE_BASEREG; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + return 1; +out: + return 0; +} + +void +EtherStop(void) { + uint8_t tmp; + + dp8390_stop(); + + tmp = ASIC_INB(NE2000_ASIC_RESET); + DELAY(10000); + ASIC_OUTB(NE2000_ASIC_RESET, tmp); + DELAY(5000); + + NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); + DELAY(5000); +} + +void +ne2000_writemem(uint8_t *src, int dst, size_t len) +{ + size_t i; + int maxwait = 100; /* about 120us */ + + /* Select page 0 registers. */ + NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); + + /* Reset remote DMA complete flag. */ + NIC_OUTB(ED_P0_ISR, ED_ISR_RDC); + + /* Set up DMA byte count. */ + NIC_OUTB(ED_P0_RBCR0, len); + NIC_OUTB(ED_P0_RBCR1, len >> 8); + + /* Set up destination address in NIC mem. */ + NIC_OUTB(ED_P0_RSAR0, dst); + NIC_OUTB(ED_P0_RSAR1, dst >> 8); + + /* Set remote DMA write. */ + NIC_OUTB(ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA); + +#ifdef NE_16BIT + for (i = 0; i < len; i += 2, src += 2) + ASIC_OUTW(NE2000_ASIC_DATA, *(uint16_t *)src); +#else + for (i = 0; i < len; i++) + ASIC_OUTB(NE2000_ASIC_DATA, *src++); +#endif + + /* + * Wait for remote DMA to complete. This is necessary because on the + * transmit side, data is handled internally by the NIC in bursts, and + * we can't start another remote DMA until this one completes. Not + * waiting causes really bad things to happen - like the NIC wedging + * the bus. + */ + while (((NIC_INB(ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait) + DELAY(1); + + if (maxwait == 0) + printf("ne2000_writemem: failed to complete\n"); +} + +void +ne2000_readmem(int src, uint8_t *dst, size_t amount) +{ + size_t i; + + /* Select page 0 registers. */ + NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); + + /* Round up to a word. */ + if (amount & 1) + ++amount; + + /* Set up DMA byte count. */ + NIC_OUTB(ED_P0_RBCR0, amount); + NIC_OUTB(ED_P0_RBCR1, amount >> 8); + + /* Set up source address in NIC mem. */ + NIC_OUTB(ED_P0_RSAR0, src); + NIC_OUTB(ED_P0_RSAR1, src >> 8); + + NIC_OUTB(ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA); + +#ifdef NE_16BIT + for (i = 0; i < amount; i += 2, dst += 2) + *(uint16_t *)dst = ASIC_INW(NE2000_ASIC_DATA); +#else + for (i = 0; i < amount; i++) + *dst++ = ASIC_INB(NE2000_ASIC_DATA); +#endif +} diff --git a/sys/arch/i386/stand/lib/netif/ne.h b/sys/arch/i386/stand/lib/netif/ne.h new file mode 100644 index 000000000..755a155f8 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/ne.h @@ -0,0 +1,4 @@ +/* $NetBSD: ne.h,v 1.3 2008/12/14 18:46:33 christos Exp $ */ + +void ne2000_readmem(int, uint8_t *, size_t); +void ne2000_writemem(uint8_t *, int, size_t); diff --git a/sys/arch/i386/stand/lib/netif/netif_small.c b/sys/arch/i386/stand/lib/netif/netif_small.c new file mode 100644 index 000000000..0a46233df --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/netif_small.c @@ -0,0 +1,165 @@ +/* $NetBSD: netif_small.c,v 1.12 2009/10/21 23:12:09 snj Exp $ */ + +/* minimal netif - for boot ROMs we don't have to select between + several interfaces, and we have to save space + + hacked from netbsd:sys/arch/mvme68k/stand/libsa/netif.c + */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include +#include + +#include +#include + +#include "netif_small.h" +#include "etherdrv.h" + +#ifdef NETIF_DEBUG +int netif_debug = 1; +#endif + +/* we allow for one socket only */ +static struct iodesc iosocket; + +struct iodesc * +socktodesc(int sock) +{ + if (sock != 0) { + return NULL; + } + return &iosocket; +} + +int +netif_open(void) +{ + struct iodesc *io; + + io = &iosocket; + if (io->io_netif) { +#ifdef NETIF_DEBUG + printf("netif_open: device busy\n"); +#endif + return -1; + } + memset(io, 0, sizeof(*io)); + + if (!EtherInit(io->myea)) { + printf("EtherInit failed\n"); + return -1; + } + + io->io_netif = (void*)1; /* mark busy */ + + return 0; +} + +void +netif_close(int fd) +{ + struct iodesc *io; + + if (fd != 0) { + return; + } + + io = &iosocket; + if (io->io_netif) { + EtherStop(); + io->io_netif = NULL; + } +} + +/* + * Send a packet. The ether header is already there. + * Return the length sent (or -1 on error). + */ +int +netif_put(struct iodesc *desc, void *pkt, size_t len) +{ +#ifdef NETIF_DEBUG + if (netif_debug) { + struct ether_header *eh; + + printf("netif_put: desc=%p pkt=%p len=%d\n", + desc, pkt, len); + eh = pkt; + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + return EtherSend(pkt, len); +} + +/* + * Receive a packet, including the ether header. + * Return the total length received (or -1 on error). + */ +int +netif_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timo) +{ + int len; + satime_t t; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_get: pkt=%p, maxlen=%d, tmo=%d\n", + pkt, maxlen, timo); +#endif + + t = getsecs(); + len = 0; + while (((getsecs() - t) < timo) && !len) { + len = EtherReceive(pkt, maxlen); + } + +#ifdef NETIF_DEBUG + if (netif_debug) { + struct ether_header *eh = pkt; + + printf("dst: %s ", ether_sprintf(eh->ether_dhost)); + printf("src: %s ", ether_sprintf(eh->ether_shost)); + printf("type: 0x%x\n", eh->ether_type & 0xFFFF); + } +#endif + + return len; +} diff --git a/sys/arch/i386/stand/lib/netif/netif_small.h b/sys/arch/i386/stand/lib/netif/netif_small.h new file mode 100644 index 000000000..2c80d022d --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/netif_small.h @@ -0,0 +1,35 @@ +/* $NetBSD: netif_small.h,v 1.5 2009/10/21 23:12:09 snj Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + +/* minimal netif - for boot ROMs we don't have to select between + several interfaces, and we have to save space */ + +int netif_open(void); +void netif_close(int); diff --git a/sys/arch/i386/stand/lib/netif/pcnet_isapnp.c b/sys/arch/i386/stand/lib/netif/pcnet_isapnp.c new file mode 100644 index 000000000..b45db94cb --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/pcnet_isapnp.c @@ -0,0 +1,89 @@ +/* $NetBSD: pcnet_isapnp.c,v 1.8 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "etherdrv.h" +#include "lance.h" + +#ifndef ISAPNPID +#define ISAPNPID 0x516e0010 /* TKN0010 */ +#endif + +int lance_rap, lance_rdp; + +u_char eth_myaddr[6]; + +extern void am7990_init(void); +extern void am7990_stop(void); + +static struct btinfo_netif bi_netif; + +int +EtherInit(unsigned char *myadr) +{ + int iobase, dmachan, i; + + if (isapnp_finddev(ISAPNPID, &iobase, &dmachan)) { + printf("cannot find PCNET\n"); + return 0; + } + + printf("printf using PCNET @ %x\n", iobase); + + lance_rap = iobase + 0x12; + lance_rdp = iobase + 0x10; + + /* make sure it's stopped */ + am7990_stop(); + + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i] = inb(iobase + i); + + isa_dmacascade(dmachan); + + am7990_init(); + + strncpy(bi_netif.ifname, "le", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_ISA; + bi_netif.addr.iobase = iobase; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); + + return 1; +} diff --git a/sys/arch/i386/stand/lib/netif/pcnet_pci.c b/sys/arch/i386/stand/lib/netif/pcnet_pci.c new file mode 100644 index 000000000..a0712acaa --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/pcnet_pci.c @@ -0,0 +1,99 @@ +/* $NetBSD: pcnet_pci.c,v 1.8 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include +#include +#include +#include + +#include +#include +#include + +#include "etherdrv.h" +#include "lance.h" + +int lance_rap, lance_rdp; + +static pcihdl_t hdl; + +u_char eth_myaddr[6]; + +extern void am7990_init(void); +extern void am7990_stop(void); + +static struct btinfo_netif bi_netif; + +int +EtherInit(unsigned char *myadr) +{ + int iobase, pcicsr, i; + + if (pcicheck() == -1) { + printf("cannot access PCI\n"); + return 0; + } + + if (pcifinddev(0x1022, 0x2000, &hdl)) { + printf("cannot find PCNET\n"); + return 0; + } + + if (pcicfgread(&hdl, 0x10, &iobase) || !(iobase & 1)) { + printf("cannot map IO space\n"); + return 0; + } + iobase &= 0xfffffffc; + + lance_rap = iobase + 0x12; + lance_rdp = iobase + 0x10; + + /* make sure it's stopped */ + am7990_stop(); + + /* enable bus mastering in PCI command register */ + if (pcicfgread(&hdl, 0x04, &pcicsr) + || pcicfgwrite(&hdl, 0x04, pcicsr | 4)) { + printf("cannot enable DMA\n"); + return 0; + } + + for (i = 0; i < 6; i++) + myadr[i] = eth_myaddr[i] = inb(iobase + i); + + am7990_init(); + + strncpy(bi_netif.ifname, "le", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_PCI; + bi_netif.addr.tag = hdl; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); + + return 1; +} diff --git a/sys/arch/i386/stand/lib/netif/wd80x3.c b/sys/arch/i386/stand/lib/netif/wd80x3.c new file mode 100644 index 000000000..e913f8d71 --- /dev/null +++ b/sys/arch/i386/stand/lib/netif/wd80x3.c @@ -0,0 +1,323 @@ +/* $NetBSD: wd80x3.c,v 1.10 2008/12/14 18:46:33 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Device driver for National Semiconductor DS8390/WD83C690 based ethernet + * adapters. + * + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * + * Copyright (C) 1993, David Greenman. This software may be used, modified, + * copied, distributed, and sold, in both source and binary form provided that + * the above copyright and these terms are retained. Under no circumstances is + * the author responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with its use. + */ + +/* + * Device driver for the Western Digital/SMC 8003 and 8013 series, + * and the SMC Elite Ultra (8216). + */ + +#include +#include + +#include +#include + +#ifdef _STANDALONE +#include +#include +#endif + +#include "etherdrv.h" +#include +#include "dp8390.h" +#include + +#ifndef BASEREG +#define BASEREG 0x240 +#define BASEMEM 0xd0000 +#endif + +#define WD_BASEREG BASEREG +#define WD_BASEMEM BASEMEM + +#ifndef _STANDALONE +extern int mapio(void); +#endif + +u_char eth_myaddr[6]; + +static uint8_t we_type; +static int we_is16bit; + +#ifdef _STANDALONE +static struct btinfo_netif bi_netif; +#endif + +const char * +we_params(void) +{ + const char *typestr; + + dp8390_memsize = 8192; + + we_type = inb(WD_BASEREG + WE_CARD_ID); + switch (we_type) { +#ifdef SUPPORT_WD80X3 + case WE_TYPE_WD8003S: + typestr = "WD8003S"; + break; + case WE_TYPE_WD8003E: + typestr = "WD8003E"; + break; + case WE_TYPE_WD8003EB: + typestr = "WD8003EB"; + break; + case WE_TYPE_WD8003W: + typestr = "WD8003W"; + break; + case WE_TYPE_WD8013EBT: + typestr = "WD8013EBT"; + dp8390_memsize = 16384; + we_is16bit = 1; + break; + case WE_TYPE_WD8013W: + typestr = "WD8013W"; + dp8390_memsize = 16384; + we_is16bit = 1; + break; + case WE_TYPE_WD8013EP: /* also WD8003EP */ + if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) { + we_is16bit = 1; + dp8390_memsize = 16384; + typestr = "WD8013EP"; + } else + typestr = "WD8003EP"; + break; + case WE_TYPE_WD8013WC: + typestr = "WD8013WC"; + dp8390_memsize = 16384; + we_is16bit = 1; + break; + case WE_TYPE_WD8013EBP: + typestr = "WD8013EBP"; + dp8390_memsize = 16384; + we_is16bit = 1; + break; + case WE_TYPE_WD8013EPC: + typestr = "WD8013EPC"; + dp8390_memsize = 16384; + we_is16bit = 1; + break; +#endif +#ifdef SUPPORT_SMC_ULTRA + case WE_TYPE_SMC8216C: + case WE_TYPE_SMC8216T: + { + uint8_t hwr; + + typestr = (we_type == WE_TYPE_SMC8216C) ? + "SMC8216/SMC8216C" : "SMC8216T"; + + hwr = inb(WD_BASEREG + WE790_HWR); + outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH); + switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) { + case WE790_RAR_SZ64: + dp8390_memsize = 65536; + break; + case WE790_RAR_SZ32: + dp8390_memsize = 32768; + break; + case WE790_RAR_SZ16: + dp8390_memsize = 16384; + break; + case WE790_RAR_SZ8: + /* 8216 has 16K shared mem -- 8416 has 8K */ + typestr = (we_type == WE_TYPE_SMC8216C) ? + "SMC8416C/SMC8416BT" : "SMC8416T"; + dp8390_memsize = 8192; + break; + } + outb(WD_BASEREG + WE790_HWR, hwr); + + we_is16bit = 1; +#ifdef SUPPORT_WD80X3 + dp8390_is790 = 1; +#endif + break; + } +#endif + default: + /* Not one we recognize. */ + return NULL; + } + + /* + * Make some adjustments to initial values depending on what is + * found in the ICR. + */ + if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) && + (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) { + we_is16bit = 0; + dp8390_memsize = 8192; + } + +#ifdef WE_DEBUG + { + int i; + + printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, " + "memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize); + for (i = 0; i < 8; i++) + printf(" %d -> 0x%x\n", i, + inb(WD_BASEREG + i)); + } +#endif + + return typestr; +} + +int +EtherInit(unsigned char *myadr) +{ + const char *typestr; + uint8_t x; + int i; + uint8_t laar_proto; + uint8_t msr_proto; + + dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET; + dp8390_membase = WD_BASEMEM; + +#ifndef _STANDALONE + if (mapio()) { + printf("no IO access\n"); + return 0; + } +#endif + + for (x = 0, i = 0; i < 8; i++) + x += inb(WD_BASEREG + WE_PROM + i); + + if (x != WE_ROM_CHECKSUM_TOTAL) + return 0; + + /* reset the ethernet card */ + outb(WD_BASEREG + WE_MSR, WE_MSR_RST); + delay(100); + outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST); + delay(5000); + + typestr = we_params(); + if (!typestr) + return 0; + + printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n", + typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize); + + /* get ethernet address */ + for (i = 0; i < 6; i++) + eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i); + + /* + * Set upper address bits and 8/16 bit access to shared memory. + */ + if (dp8390_is790) { + laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN; + outb(WD_BASEREG + WE_LAAR, laar_proto | + (we_is16bit ? WE_LAAR_M16EN : 0)); + } else if ((we_type & WE_SOFTCONFIG) || + (we_type == WE_TYPE_WD8013EBT)) { + laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI; + if (we_is16bit) + laar_proto |= WE_LAAR_L16EN; + outb(WD_BASEREG + WE_LAAR, laar_proto | + (we_is16bit ? WE_LAAR_M16EN : 0)); + } + + /* + * Set address and enable interface shared memory. + */ + if (dp8390_is790) { + /* XXX MAGIC CONSTANTS XXX */ + x = inb(WD_BASEREG + 0x04); + outb(WD_BASEREG + 0x04, x | 0x80); + outb(WD_BASEREG + 0x0b, + ((WD_BASEMEM >> 13) & 0x0f) | + ((WD_BASEMEM >> 11) & 0x40) | + (inb(WD_BASEREG + 0x0b) & 0xb0)); + outb(WD_BASEREG + 0x04, x); + msr_proto = 0x00; + dp8390_cr_proto = 0x00; + } else { + msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR; + dp8390_cr_proto = ED_CR_RD2; + } + + outb(WD_BASEREG + WE_MSR, msr_proto | WE_MSR_MENB); + delay(2); + + /* + * DCR gets: + * + * FIFO threshold to 8, No auto-init Remote DMA, + * byte order=80x86. + * + * 16-bit cards also get word-wide DMA transfers. + */ + dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0); + + if (dp8390_config()) + return 0; + +#ifdef _STANDALONE + strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname)); + bi_netif.bus = BI_BUS_ISA; + bi_netif.addr.iobase = WD_BASEREG; + + BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); +#endif + return 1; +} + +/* + * Stop ethernet board + */ +void +EtherStop(void) { + /* stop dp8390, followed by a board reset */ + dp8390_stop(); + outb(WD_BASEREG + WE_MSR, WE_MSR_RST); + outb(WD_BASEREG + WE_MSR, 0); +} diff --git a/sys/arch/i386/stand/lib/parseutils.c b/sys/arch/i386/stand/lib/parseutils.c new file mode 100644 index 000000000..37099d187 --- /dev/null +++ b/sys/arch/i386/stand/lib/parseutils.c @@ -0,0 +1,151 @@ +/* $NetBSD: parseutils.c,v 1.6 2011/08/18 13:20:04 christos Exp $ */ + +/* + * Copyright (c) 1996, 1997 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996, 1997 + * Perry E. Metzger. All rights reserved. + * Copyright (c) 1997 + * Jason R. Thorpe. All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "libi386.h" + +/* + * chops the head from the arguments and returns the arguments if any, + * or possibly an empty string. + */ +char * +gettrailer(char *arg) +{ + char *options; + + for (options = arg; *options; options++) { + switch (*options) { + case ' ': + case '\t': + *options++ = '\0'; + break; + default: + continue; + } + break; + } + if (*options == '\0') + return ""; + + /* trim leading blanks/tabs */ + while (*options == ' ' || *options == '\t') + options++; + + return options; +} + +int +parseopts(const char *opts, int *howto) +{ + int r, tmpopt = 0; + + opts++; /* skip - */ + while (*opts) { + r = 0; + BOOT_FLAG(*opts, r); + if (r == 0) { + printf("-%c: unknown flag\n", *opts); + command_help(NULL); + return 0; + } + tmpopt |= r; + opts++; + if (*opts == ' ' || *opts == '\t') { + do + opts++; /* skip whitespace */ + while (*opts == ' ' || *opts == '\t'); + if (*opts == '-') + opts++; /* skip - */ + else if (*opts != '\0') { + printf("invalid arguments\n"); + command_help(NULL); + return 0; + } + } + } + + *howto = tmpopt; + return 1; +} + +int +parseboot(char *arg, char **filename, int *howto) +{ + char *opts = NULL; + + *filename = 0; + *howto = 0; + + /* if there were no arguments */ + if (!*arg) + return 1; + + /* format is... */ + /* [[xxNx:]filename] [-adqsv] */ + + /* check for just args */ + if (arg[0] == '-') + opts = arg; + else { + /* there's a file name */ + *filename = arg; + + opts = gettrailer(arg); + if (!*opts) + opts = NULL; + else if (*opts != '-') { + printf("invalid arguments\n"); + command_help(NULL); + return 0; + } + } + + /* at this point, we have dealt with filenames. */ + + /* now, deal with options */ + if (opts) { + if (parseopts(opts, howto) == 0) + return 0; + } + + return 1; +} diff --git a/sys/arch/i386/stand/lib/pcio.c b/sys/arch/i386/stand/lib/pcio.c new file mode 100644 index 000000000..d03e4466b --- /dev/null +++ b/sys/arch/i386/stand/lib/pcio.c @@ -0,0 +1,378 @@ +/* $NetBSD: pcio.c,v 1.30 2011/06/08 16:04:40 joerg Exp $ */ + +/* + * Copyright (c) 1996, 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * console I/O + * needs lowlevel routines from conio.S and comio.S + */ + +#include +#include +#include + +#include "libi386.h" +#include "bootinfo.h" + +extern struct x86_boot_params boot_params; + +struct btinfo_console btinfo_console; + +#ifdef SUPPORT_SERIAL +static int iodev; + +#ifdef DIRECT_SERIAL +#include "comio_direct.h" + +#define cominit_x() btinfo_console.speed = \ + cominit_d(btinfo_console.addr, btinfo_console.speed) +#define computc_x(ch) computc_d(ch, btinfo_console.addr) +#define comgetc_x() comgetc_d(btinfo_console.addr) +#define comstatus_x() comstatus_d(btinfo_console.addr) + +#else +#define cominit_x() cominit(iodev - CONSDEV_COM0) +#define computc_x(ch) computc(ch, iodev - CONSDEV_COM0) +#define comgetc_x() comgetc(iodev - CONSDEV_COM0) +#define comstatus_x() comstatus(iodev - CONSDEV_COM0) + +#endif /* DIRECT_SERIAL */ + +static int getcomaddr(int); +#endif /* SUPPORT_SERIAL */ + +#define POLL_FREQ 10 + +static void +wait(int us) +{ + int prev = biosgetsystime(); + int tgt = prev + (20 * us) / 1000000; + int new; + + while ((new = biosgetsystime()) < tgt) { + if (new < prev) /* XXX timer wrapped */ + break; + prev = new; + } +} + +#ifdef SUPPORT_SERIAL +static int +getcomaddr(int idx) +{ + short addr; +#ifdef CONSADDR + if (CONSADDR != 0) + return CONSADDR; +#endif + /* read in BIOS data area */ + pvbcopy((void *)(0x400 + 2 * idx), &addr, 2); + return addr; +} +#endif + +void +clear_pc_screen(void) +{ +#ifdef SUPPORT_SERIAL + /* Clear the screen if we are on a glass tty. */ + if (iodev == CONSDEV_PC) + conclr(); +#endif +} + +void +initio(int dev) +{ +#ifdef SUPPORT_SERIAL + int i; + +#if defined(DIRECT_SERIAL) && defined(CONSPEED) + btinfo_console.speed = CONSPEED; +#else + btinfo_console.speed = 9600; +#endif + + switch (dev) { + case CONSDEV_AUTO: + for (i = 0; i < 3; i++) { + iodev = CONSDEV_COM0 + i; + btinfo_console.addr = getcomaddr(i); + if (!btinfo_console.addr) + break; + conputc('0' + i); /* to tell user what happens */ + cominit_x(); +#ifdef DIRECT_SERIAL + /* check for: + * 1. successful output + * 2. optionally, keypress within 7s + */ + if ( computc_x(':') && + computc_x('-') && + computc_x('(') +#ifdef COMCONS_KEYPRESS + && awaitkey(7, 0) +#endif + ) + goto ok; +#else /* ! DIRECT_SERIAL */ + /* + * serial console must have hardware handshake! + * check: + * 1. character output without error + * 2. status bits for modem ready set + * (status seems only useful after character output) + * 3. optionally, keypress within 7s + */ + if (!(computc_x('@') & 0x80) + && (comstatus_x() & 0x00b0) +#ifdef COMCONS_KEYPRESS + && awaitkey(7, 0) +#endif + ) + goto ok; +#endif /* DIRECT_SERIAL */ + } + iodev = CONSDEV_PC; +ok: + break; + case CONSDEV_COM0: + case CONSDEV_COM1: + case CONSDEV_COM2: + case CONSDEV_COM3: + iodev = dev; + btinfo_console.addr = getcomaddr(iodev - CONSDEV_COM0); + if (!btinfo_console.addr) + goto nocom; + cominit_x(); + break; + case CONSDEV_COM0KBD: + case CONSDEV_COM1KBD: + case CONSDEV_COM2KBD: + case CONSDEV_COM3KBD: + iodev = dev - CONSDEV_COM0KBD + CONSDEV_COM0; + i = iodev - CONSDEV_COM0; + btinfo_console.addr = getcomaddr(i); + if (!btinfo_console.addr) + goto nocom; + conputc('0' + i); /* to tell user what happens */ + cominit_x(); +#ifdef DIRECT_SERIAL + /* check for: + * 1. successful output + * 2. optionally, keypress within 7s + */ + if ( computc_x(':') && + computc_x('-') && + computc_x('(') +#ifdef COMCONS_KEYPRESS + && awaitkey(7, 0) +#endif + ) + break; +#else /* ! DIRECT_SERIAL */ + /* + * serial console must have hardware handshake! + * check: + * 1. character output without error + * 2. status bits for modem ready set + * (status seems only useful after character output) + * 3. optionally, keypress within 7s + */ + if (!(computc_x('@') & 0x80) + && (comstatus_x() & 0x00b0) +#ifdef COMCONS_KEYPRESS + && awaitkey(7, 0) +#endif + ) + break; +#endif /* DIRECT_SERIAL */ + default: +nocom: + iodev = CONSDEV_PC; + break; + } + conputc('\015'); + conputc('\n'); + strncpy(btinfo_console.devname, iodev == CONSDEV_PC ? "pc" : "com", 16); + +#else /* !SUPPORT_SERIAL */ + btinfo_console.devname[0] = 'p'; + btinfo_console.devname[1] = 'c'; + btinfo_console.devname[2] = 0; +#endif /* SUPPORT_SERIAL */ +} + +static inline void internal_putchar(int); + +static inline void +internal_putchar(int c) +{ +#ifdef SUPPORT_SERIAL + switch (iodev) { + case CONSDEV_PC: +#endif + conputc(c); +#ifdef SUPPORT_SERIAL + break; + case CONSDEV_COM0: + case CONSDEV_COM1: + case CONSDEV_COM2: + case CONSDEV_COM3: + computc_x(c); + break; + } +#endif +} + +void +putchar(int c) +{ + if (c == '\n') + internal_putchar('\r'); + internal_putchar(c); +} + +int +getchar(void) +{ + int c; +#ifdef SUPPORT_SERIAL + switch (iodev) { + default: /* to make gcc -Wall happy... */ + case CONSDEV_PC: +#endif + while (!coniskey()) + ; + c = congetc(); +#ifdef CONSOLE_KEYMAP + { + char *cp = strchr(CONSOLE_KEYMAP, c); + if (cp != 0 && cp[1] != 0) + c = cp[1]; + } +#endif + return c; +#ifdef SUPPORT_SERIAL + case CONSDEV_COM0: + case CONSDEV_COM1: + case CONSDEV_COM2: + case CONSDEV_COM3: +#ifdef DIRECT_SERIAL + c = comgetc_x(); +#else + do { + c = comgetc_x(); + } while ((c >> 8) == 0xe0); /* catch timeout */ +#ifdef COMDEBUG + if (c & 0x8000) { + printf("com input %x, status %x\n", + c, comstatus_x()); + } +#endif + c &= 0xff; +#endif /* DIRECT_SERIAL */ + return c; + } +#endif /* SUPPORT_SERIAL */ +} + +int +iskey(int intr) +{ +#ifdef SUPPORT_SERIAL + switch (iodev) { + default: /* to make gcc -Wall happy... */ + case CONSDEV_PC: +#endif + return (intr && conisshift()) || coniskey(); +#ifdef SUPPORT_SERIAL + case CONSDEV_COM0: + case CONSDEV_COM1: + case CONSDEV_COM2: + case CONSDEV_COM3: +#ifdef DIRECT_SERIAL + return !!comstatus_x(); +#else + return !!(comstatus_x() & 0x0100); +#endif + } +#endif /* SUPPORT_SERIAL */ +} + +char +awaitkey(int timeout, int tell) +{ + int i; + char c = 0; + + i = timeout * POLL_FREQ; + + for (;;) { + if (tell && (i % POLL_FREQ) == 0) { + char numbuf[32]; + int len; + + len = snprintf(numbuf, sizeof(numbuf), "%d seconds. ", + i/POLL_FREQ); + if (len > 0 && len < sizeof(numbuf)) { + char *p = numbuf; + + printf("%s", numbuf); + while (*p) + *p++ = '\b'; + printf("%s", numbuf); + } + } + if (iskey(1)) { + /* flush input buffer */ + while (iskey(0)) + c = getchar(); + if (c == 0) + c = -1; + goto out; + } + if (i--) + wait(1000000 / POLL_FREQ); + else + break; + } + +out: + if (tell) + printf("0 seconds. \n"); + + return c; +} + +void +wait_sec(int sec) +{ + + wait(sec * 1000000); +} diff --git a/sys/arch/i386/stand/lib/pcivar.h b/sys/arch/i386/stand/lib/pcivar.h new file mode 100644 index 000000000..f6f9e438b --- /dev/null +++ b/sys/arch/i386/stand/lib/pcivar.h @@ -0,0 +1,35 @@ +/* $NetBSD: pcivar.h,v 1.4 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +typedef unsigned int pcihdl_t; + +int pcicheck(void); +int pcifinddev(int, int, pcihdl_t*); +int pcicfgread(pcihdl_t*, int, int*); +int pcicfgwrite(pcihdl_t*, int, int); diff --git a/sys/arch/i386/stand/lib/pread.c b/sys/arch/i386/stand/lib/pread.c new file mode 100644 index 000000000..fc273a7bf --- /dev/null +++ b/sys/arch/i386/stand/lib/pread.c @@ -0,0 +1,70 @@ +/* $NetBSD: pread.c,v 1.7 2008/12/14 17:03:43 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* read into destination in flat addr space */ + +#include + +#include "libi386.h" + +#ifdef SAVE_MEMORY +#define BUFSIZE (1*1024) +#else +#define BUFSIZE (4*1024) +#endif + +static char *buf; + +ssize_t +pread(int fd, void *dest, size_t size) +{ + int rsize; + + if (!buf) + buf = alloc(BUFSIZE); + + rsize = size; + while (rsize > 0) { + int count, got; + + count = (rsize < BUFSIZE ? rsize : BUFSIZE); + + got = read(fd, buf, count); + if (got < 0) + return -1; + + /* put to physical space */ + vpbcopy(buf, dest, got); + + dest += got; + rsize -= got; + if (got < count) + break; /* EOF */ + } + return size - rsize; +} diff --git a/sys/arch/i386/stand/lib/printmemlist.c b/sys/arch/i386/stand/lib/printmemlist.c new file mode 100644 index 000000000..bbf5153df --- /dev/null +++ b/sys/arch/i386/stand/lib/printmemlist.c @@ -0,0 +1,57 @@ +/* $NetBSD: printmemlist.c,v 1.2 2008/12/14 17:03:43 christos Exp $ */ +/* + * Copyright (c) 1999 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "libi386.h" + +extern int getmementry(int *, int *); + +static char *memtypes[] = { + "available", + "reserved", + "ACPI reclaimable", + "ACPI NVS" +}; + +void +printmemlist(void) +{ + int buf[5], i; + char *type; + + i = 0; + do { + if (getmementry(&i, buf)) + break; + if (buf[4] < 1 || buf[4] > 4) + type = "invalid entry"; + else + type = memtypes[buf[4] - 1]; + printf("%x:%x/%x:%x: %s\n", buf[1], buf[0], buf[3], buf[2], + type); + } while (i); +} diff --git a/sys/arch/i386/stand/lib/putstr.S b/sys/arch/i386/stand/lib/putstr.S new file mode 100644 index 000000000..d29ae9ac1 --- /dev/null +++ b/sys/arch/i386/stand/lib/putstr.S @@ -0,0 +1,84 @@ +/* $NetBSD: putstr.S,v 1.2 2008/04/28 20:23:25 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* + * Diagnostic print routines callable from 32bit C code during early + * parts of the boot process. + */ + +/* + * void putstr(const char *) + * + * display message on console + * bugs: message address must be less than 64k + */ + + .globl _C_LABEL(putstr) +_C_LABEL(putstr): + .code32 + movl 4(%esp), %eax + pusha + movl %eax, %esi + + call _C_LABEL(prot_to_real) + .code16 + + movl %esi, %eax + call message + + calll _C_LABEL(real_to_prot) + .code32 + popa + ret + +/* + * void putint(int) + * + * display value on console as 8 hex digits followed by a space + */ + + .globl _C_LABEL(putint) +_C_LABEL(putint): + .code32 + movl 4(%esp), %eax + pusha + + call _C_LABEL(prot_to_real) + .code16 + + call dump_eax + + calll _C_LABEL(real_to_prot) + .code32 + popa + ret diff --git a/sys/arch/i386/stand/lib/putstr32.S b/sys/arch/i386/stand/lib/putstr32.S new file mode 100644 index 000000000..e700dd5d2 --- /dev/null +++ b/sys/arch/i386/stand/lib/putstr32.S @@ -0,0 +1,69 @@ +/* $NetBSD: putstr32.S,v 1.1 2011/06/02 18:53:00 dsl Exp $ */ + +/*- + * Copyright (c) 20011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* + * Diagnostic print routines callable from 32bit C code during early + * parts of the boot process. + */ + +/* + * void putstr(const char *) + * + * display message on serial port + */ + + .globl _C_LABEL(putstr32) +_C_LABEL(putstr32): + .code32 + push %esi + movl 8(%esp), %esi + + call message32 + + pop %esi + ret + +/* + * void putint(int) + * + * display value on serial port as 8 hex digits followed by a space + */ + + .globl _C_LABEL(putint32) +_C_LABEL(putint32): + .code32 + movl 4(%esp), %eax + + call dump_eax32 + + ret diff --git a/sys/arch/i386/stand/lib/pvcopy.S b/sys/arch/i386/stand/lib/pvcopy.S new file mode 100644 index 000000000..d73bff583 --- /dev/null +++ b/sys/arch/i386/stand/lib/pvcopy.S @@ -0,0 +1,115 @@ +/* $NetBSD: pvcopy.S,v 1.2 2008/04/28 20:23:25 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* + * Routines to copy to/from absolute virtual addresses. + * Needed because the boot code runs with %ds having a 64k offset + * whereas Unix runs with a zero offset. + * + * These routines are optimised for code space, not execution speed. + */ + +/* + * pbzero(void *dst, int cnt) + * zero absolute virtual memory + */ +ENTRY(pbzero) + .code32 + push %edi + push %es + mov 12(%esp),%edi + mov 16(%esp),%ecx + + mov $flatdataseg, %ax /* selector with offset == 0 */ + mov %ax, %es + xor %eax,%eax + + cld + rep + stosb + + pop %es + pop %edi + ret + +/* + * vpbcopy(const void *src, void *dst, int cnt) + * Copy to absolute virtual address + */ +ENTRY(vpbcopy) + .code32 + push %esi + push %edi + push %es + mov 16(%esp),%esi + mov 20(%esp),%edi + mov 24(%esp),%ecx + + mov $flatdataseg, %ax /* selector with offset == 0 */ + mov %ax, %es + xor %eax,%eax + + cld + rep + movsb + + popl %es + popl %edi + popl %esi + ret + +/* + * pvbcopy(const void *src, void *dst, int cnt) + * Copy from absolute virtual address + */ +ENTRY(pvbcopy) + .code32 + push %esi + push %edi + push %ds + mov 16(%esp),%esi + mov 20(%esp),%edi + mov 24(%esp),%ecx + + mov $flatdataseg, %ax /* selector with offset == 0 */ + mov %ax, %ds + xor %eax,%eax + + cld + rep + movsb + + popl %ds + popl %edi + popl %esi + ret diff --git a/sys/arch/i386/stand/lib/rasops.c b/sys/arch/i386/stand/lib/rasops.c new file mode 100644 index 000000000..70b353bfc --- /dev/null +++ b/sys/arch/i386/stand/lib/rasops.c @@ -0,0 +1,91 @@ +/* $NetBSD: rasops.c,v 1.1 2009/02/16 22:39:30 jmcneill Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* ANSI colormap (R,G,B). Upper 8 are high-intensity */ +const uint8_t rasops_cmap[256*3] = { + 0x00, 0x00, 0x00, /* black */ + 0x7f, 0x00, 0x00, /* red */ + 0x00, 0x7f, 0x00, /* green */ + 0x7f, 0x7f, 0x00, /* brown */ + 0x00, 0x00, 0x7f, /* blue */ + 0x7f, 0x00, 0x7f, /* magenta */ + 0x00, 0x7f, 0x7f, /* cyan */ + 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ + + 0x7f, 0x7f, 0x7f, /* black */ + 0xff, 0x00, 0x00, /* red */ + 0x00, 0xff, 0x00, /* green */ + 0xff, 0xff, 0x00, /* brown */ + 0x00, 0x00, 0xff, /* blue */ + 0xff, 0x00, 0xff, /* magenta */ + 0x00, 0xff, 0xff, /* cyan */ + 0xff, 0xff, 0xff, /* white */ + + /* + * For the cursor, we need at least the last (255th) + * color to be white. Fill up white completely for + * simplicity. + */ +#define _CMWHITE 0xff, 0xff, 0xff, +#define _CMWHITE16 _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ + _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ + _CMWHITE _CMWHITE _CMWHITE _CMWHITE \ + _CMWHITE _CMWHITE _CMWHITE _CMWHITE + _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 + _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 + _CMWHITE16 _CMWHITE16 _CMWHITE16 _CMWHITE16 /* but not the last one */ +#undef _CMWHITE16 +#undef _CMWHITE + + /* + * For the cursor the fg/bg indices are bit inverted, so + * provide complimentary colors in the upper 16 entries. + */ + 0x7f, 0x7f, 0x7f, /* black */ + 0xff, 0x00, 0x00, /* red */ + 0x00, 0xff, 0x00, /* green */ + 0xff, 0xff, 0x00, /* brown */ + 0x00, 0x00, 0xff, /* blue */ + 0xff, 0x00, 0xff, /* magenta */ + 0x00, 0xff, 0xff, /* cyan */ + 0xff, 0xff, 0xff, /* white */ + + 0x00, 0x00, 0x00, /* black */ + 0x7f, 0x00, 0x00, /* red */ + 0x00, 0x7f, 0x00, /* green */ + 0x7f, 0x7f, 0x00, /* brown */ + 0x00, 0x00, 0x7f, /* blue */ + 0x7f, 0x00, 0x7f, /* magenta */ + 0x00, 0x7f, 0x7f, /* cyan */ + 0xc7, 0xc7, 0xc7, /* white - XXX too dim? */ +}; diff --git a/sys/arch/i386/stand/lib/realprot.S b/sys/arch/i386/stand/lib/realprot.S new file mode 100644 index 000000000..2d4bf9304 --- /dev/null +++ b/sys/arch/i386/stand/lib/realprot.S @@ -0,0 +1,296 @@ +/* $NetBSD: realprot.S,v 1.10 2010/12/19 17:18:23 jakllsch Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Loosely based on code from stand/lib/libcrt/bootsect/start_bootsect.S + */ + +#include + +#define CR0_PE 1 + + .text + .align 16 +gdt: + .word 0, 0 + .byte 0, 0x00, 0x00, 0 + + /* kernel code segment */ + .globl flatcodeseg +flatcodeseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9f, 0xcf, 0 + + /* kernel data segment */ + .globl flatdataseg +flatdataseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x93, 0xcf, 0 + + /* boot code segment, base will be patched */ +bootcodeseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9e, 0x4f, 0 + + /* boot data segment, base will be patched */ +bootdataseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x92, 0xcf, 0 + + /* 16 bit real mode, base will be patched */ +bootrealseg = . - gdt + .word 0xffff, 0 + .byte 0, 0x9e, 0x00, 0 + + /* limits (etc) for data segment in real mode */ +bootrealdata = . - gdt + .word 0xffff, 0 + .byte 0, 0x92, 0x00, 0 +gdtlen = . - gdt + + .align 16 +gdtarg: + .word gdtlen-1 /* limit */ + .long 0 /* physical addr, will be inserted */ + +toreal: .word xreal /* off:seg address for indirect jump */ +ourseg: .word 0 /* real mode code and data segment */ + +stkseg: .word 0 /* real mode stack segment */ +stkdif: .long 0 /* diff. between real and prot sp */ + + .global gdt_fixup +gdt_fixup: + .code16 + pushl %eax + pushl %edx + + xorl %eax, %eax + mov %cs, %ax + mov %ax, ourseg + /* sort out stuff for %ss != %ds */ + xorl %edx, %edx + movw %ss, %dx + movw %dx, stkseg + subl %eax, %edx + shll $4, %edx + movl %edx, stkdif + + /* fix up GDT entries for bootstrap */ + mov %ax, %dx + shll $4, %eax + shr $12, %dx + +#define FIXUP(gdt_index) \ + movw %ax, gdt+gdt_index+2; \ + movb %dl, gdt+gdt_index+4 + + FIXUP(bootcodeseg) + FIXUP(bootrealseg) + FIXUP(bootdataseg) + + /* fix up GDT pointer */ + addl $gdt, %eax + movl %eax, gdtarg+2 + + popl %edx + popl %eax + ret + +/* + * real_to_prot() + * + * Switch CPU to 32bit protected mode to execute C. + * + * NB: Call with the 32bit calll instruction so that a 32 bit + * return address is pushed. + * + * All registers are preserved, %ss:%esp will point to the same + * place as %ss:%sp did, although the actual value of %esp might + * be changed. + * + * Interrupts are disabled while we are in 32bit mode to save us + * having to setup a different IDT. This code is only used during + * the boot process and it doesn't use any interrupts. + */ +ENTRY(real_to_prot) + .code16 + pushl %eax + cli + + lgdt %cs:gdtarg /* Global descriptor table */ + + movl %cr0, %eax + or $CR0_PE, %ax + movl %eax, %cr0 /* Enter 'protected mode' */ + + ljmp $bootcodeseg, $1f /* Jump into a 32bit segment */ +1: + + .code32 + /* Set all the segment registers to map the same area as the code */ + mov $bootdataseg, %eax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + addl stkdif, %esp /* Allow for real %ss != %ds */ + + popl %eax + ret + +/* + * prot_to_real() + * + * Switch CPU back to 16bit real mode in order to call system bios functions. + * + * All registers are preserved, except that %sp may be changed so that + * %ss:%sp points to the same memory. + * Note that %ebp is preserved and will not reference the correct part + * of the stack. + * + * Interrupts are enabled while in real mode. + * + * Based on the descripton in section 14.5 of the 80386 Programmer's + * reference book. + */ +/* + * EPIA_HACK + * + * VIA C3 processors (Eden, Samuel 2) don't seem to correctly switch back to + * executing 16 bit code after the switch to real mode and subsequent jump. + * + * It is speculated that the CPU is prefetching and decoding branch + * targets and not invalidating this buffer on the long jump. + * Further investication indicates that the caching of return addresses + * is most likely the problem. + * + * Previous versions just used some extra call/ret and a few NOPs, these + * only helped a bit, but booting compressed kernels would still fail. + * + * Trashing the return address stack (by doing 'call' without matched 'ret') + * Seems to fix things completely. 1 iteration isn't enough, 16 is plenty. + */ +ENTRY(prot_to_real) + .code32 + pushl %eax +#ifdef EPIA_HACK + push %ecx + push $0x10 + pop %ecx +1: call trash_return_cache + loop 1b + pop %ecx +#endif + + /* + * Load the segment registers while still in protected mode. + * Otherwise the control bits don't get changed. + * The correct base addresses are loaded later. + */ + movw $bootrealdata, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + + /* + * Load %cs with a segment that has the correct attributes for + * 16bit operation. + */ + ljmp $bootrealseg, $1f +1: + + .code16 + movl %cr0, %eax + and $~CR0_PE, %eax + movl %eax, %cr0 /* Disable potected mode */ + + /* Jump far indirect to load real mode %cs */ + ljmp *%cs:toreal +xreal: + /* + * CPU is now in real mode, load the other segment registers + * with their correct base addresses. + */ + mov %cs, %ax + mov %ax, %ds + mov %ax, %es + /* + * If stack was above 64k, 16bit %ss needs to be different from + * 32bit %ss (and the other segment registers). + */ + mov stkseg, %ax + mov %ax, %ss + subl stkdif, %esp + + /* Check we are returning to an address below 64k */ + push %bp + movw %sp, %bp + movw 2/*bp*/ + 4/*eax*/ + 2(%bp), %ax /* high bits ret addr */ + test %ax, %ax + jne 1f + pop %bp + + sti + popl %eax + retl + +1: movw $3f, %si + call message + movl 2/*bp*/ + 4/*eax*/(%bp), %eax /* return address */ + call dump_eax + int $0x18 +2: sti + hlt + jmp 2b +3: .asciz "prot_to_real can't return to " + + .global dump_eax_buff +dump_eax_buff: + . = . + 16 + +#ifdef EPIA_HACK +trash_return_cache: + .code32 + pop %eax + jmp *%eax +#endif + +/* vtophys(void *) + * convert boot time 'linear' address to a physical one + */ + +ENTRY(vtophys) + .code32 + xorl %eax, %eax + movw ourseg, %ax + shll $4, %eax + addl 4(%esp), %eax + ret diff --git a/sys/arch/i386/stand/lib/startprog.S b/sys/arch/i386/stand/lib/startprog.S new file mode 100644 index 000000000..bd6576ac6 --- /dev/null +++ b/sys/arch/i386/stand/lib/startprog.S @@ -0,0 +1,110 @@ +/* $NetBSD: startprog.S,v 1.3 2003/02/01 14:48:18 dsl Exp $ */ + +/* starts program in protected mode / flat space + with given stackframe + needs global variables flatcodeseg and flatdataseg + (gdt offsets) + derived from: NetBSD:sys/arch/i386/boot/asm.S + */ + +/* + * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include + +/* + * startprog(phyaddr,argc,argv,stack) + * start the program on protected mode where phyaddr is the entry point + */ +ENTRY(startprog) + pushl %ebp + movl %esp, %ebp + + # prepare a new stack + movl $flatdataseg, %ebx + movw %bx, %es # for arg copy + movl 20(%ebp), %eax # stack + subl $4,%eax + movl %eax, %edi + + # push some number of args onto the stack + movl 12(%ebp), %ecx # argc + + movl %ecx, %eax + decl %eax + shl $2, %eax + addl 16(%ebp), %eax # ptr to last arg + movl %eax, %esi + + std # backwards + rep + movsl + + cld # LynxOS depends on it + + movl 8(%ebp), %ecx # entry + + # set new stackptr (movsl decd sp 1 more -> dummy return address) + movw %bx, %ss + movl %edi, %esp + + # push on our entry address + movl $flatcodeseg, %ebx # segment + pushl %ebx + pushl %ecx #entry + + # convert over the other data segs + movl $flatdataseg, %ebx + mov %bx, %ds + mov %bx, %es + + # convert the PC (and code seg) + lret diff --git a/sys/arch/i386/stand/lib/test/Makefile.satest b/sys/arch/i386/stand/lib/test/Makefile.satest new file mode 100644 index 000000000..ef66abd40 --- /dev/null +++ b/sys/arch/i386/stand/lib/test/Makefile.satest @@ -0,0 +1,36 @@ +# $NetBSD: Makefile.satest,v 1.2 1999/02/19 19:53:01 drochner Exp $ + +I386_STAND_DIR?= $S/arch/i386/stand + +.PATH: ${I386_STAND_DIR}/lib/test ${I386_STAND_DIR}/lib ${I386_STAND_DIR}/libsa + +SRCS+= stand_user.c + +# Separate libsa's namespace from userland libraries. +# Should comply to "sanamespace.h". +CPPFLAGS+= -Dmain=samain -Dexit=saexit -Dfree=safree +CPPFLAGS+= -Dopen=saopen -Dclose=saclose -Dread=saread -Dwrite=sawrite +CPPFLAGS+= -Dioctl=saioctl -Dlseek=salseek +CPPFLAGS+= -Dprintf=saprintf -Dsprintf=sasprintf -Dvprintf=savprintf +CPPFLAGS+= -Dputchar=saputchar -Dgets=sagets +CPPFLAGS+= -Dstrerror=sastrerror -Derrno=saerrno + +CPPFLAGS+= -I$S/lib/libsa -I${I386_STAND_DIR}/libsa -I${I386_STAND_DIR}/lib +CPPFLAGS+= -I${I386_STAND_DIR}/lib/test -I$S + +CPPFLAGS+= -DHEAP_VARIABLE + +CFLAGS= -O -g -Wall -fwritable-strings + +LDFLAGS= -g -static -Xlinker -M +LDADD= ${LIBSA} -lz -lkvm -li386 >${PROG}.list 2>&1 +CLEANFILES+= ${PROG}.list + +.include + +### find out what to use for libsa +SA_AS= library +.include "${S}/lib/libsa/Makefile.inc" +LIBSA= ${SALIB} + +${PROG}: ${LIBSA} diff --git a/sys/arch/i386/stand/lib/test/biosdisk_user.c b/sys/arch/i386/stand/lib/test/biosdisk_user.c new file mode 100644 index 000000000..6ae1071d6 --- /dev/null +++ b/sys/arch/i386/stand/lib/test/biosdisk_user.c @@ -0,0 +1,135 @@ +/* $NetBSD: biosdisk_user.c,v 1.7 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanamespace.h" + +#include +#include +#include +#include + +#include "biosdisk_ll.h" +#include "biosdisk_user.h" + +/* + * Replacement for i386/stand/lib/bios_disk.S. + * Allows to map BIOS-like device numbers to character + * device nodes or plain files. + * The actual mapping is defined in the external table + * "emuldisktab". + */ + +static int currentdev, currentdte; +static int fd = -1; + +int +get_diskinfo(int dev) +{ + int i, retval; + + if (fd != -1) { + close(fd); + fd = -1; + } + + i = 0; + for (;;) { + if (emuldisktab[i].biosdev == -1) + break; + if (emuldisktab[i].biosdev == dev) + goto ok; + i++; + } + warnx("unknown device %x", dev); + return 0; /* triggers error in set_geometry() */ + +ok: + fd = open(emuldisktab[i].name, O_RDONLY, 0); + if (fd < 0) { + warn("open %s", emuldisktab[i].name); + return 0; + } + + currentdev = dev; + currentdte = i; + + retval = ((emuldisktab[i].cyls - 1) & 0xff) << 16; + retval |= ((emuldisktab[i].cyls - 1) & 0x300) << 6; + retval |= emuldisktab[i].spt << 8; + retval |= emuldisktab[i].heads - 1; + return retval; +} + +int +biosread(int dev, int cyl, int head, int sec, int nsec, char *buf) +{ + + if (dev != currentdev) { + warnx("biosread: unexpected device %x", dev); + return -1; + } + + if (lseek(fd, ((cyl * emuldisktab[currentdte].heads + head) + * emuldisktab[currentdte].spt + sec) * 512, + SEEK_SET) == -1) { + warn("lseek"); + return -1; + } + if (read(fd, buf, nsec * 512) != nsec * 512) { + warn("read"); + return -1; + } + return 0; +} + +int +int13_extension(int dev) +{ + + return 0; +} + +void +int13_getextinfo(int dev, struct biosdisk_ext13info *info) +{ +} + +struct ext { + int8_t size; + int8_t resvd; + int16_t cnt; + int16_t off; + int16_t seg; + int64_t sec; +}; + +int +biosextread(int dev, struct ext *ext) +{ + return -1; +} diff --git a/sys/arch/i386/stand/lib/test/biosdisk_user.h b/sys/arch/i386/stand/lib/test/biosdisk_user.h new file mode 100644 index 000000000..3f4d8f549 --- /dev/null +++ b/sys/arch/i386/stand/lib/test/biosdisk_user.h @@ -0,0 +1,52 @@ +/* $NetBSD: biosdisk_user.h,v 1.4 2005/12/11 12:17:49 christos Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Defines a mapping from device numbers to file + * names and geometry data. The table must be terminated + * by an entry with "biosdev" == -1. + */ + +struct emuldisktabentry { + int biosdev; + char *name; + int spt, heads, cyls; +}; + +extern struct emuldisktabentry emuldisktab[]; + +#if 0 +This is an example: +struct emuldisktabentry emuldisktab[] = { + {0, "/dev/rfd0a", 18, 2, 80}, + {1, "fdimage", 18, 2, 80}, + {0x80, "/dev/rwd0d", 100, 4, 1000}, + {0x81, "hdimage", 100, 4, 1000}, + {-1} +}; +#endif diff --git a/sys/arch/i386/stand/lib/test/ether_bpf.c b/sys/arch/i386/stand/lib/test/ether_bpf.c new file mode 100644 index 000000000..4fe75372e --- /dev/null +++ b/sys/arch/i386/stand/lib/test/ether_bpf.c @@ -0,0 +1,216 @@ +/* $NetBSD: ether_bpf.c,v 1.10 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanamespace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define BPFDEV "/dev/bpf0" + +#define MAXPKT 1536 + +/* + * Allows to use any configured interface with + * standalone network code. Provides the interface used + * by i386/stand/lib/netif/netif_small.c. + */ + +static int bpf = -1; + +static struct nlist nl[] = { + {"_ifnet"}, + {NULL} +}; + +int +EtherInit(char *ha) +{ + int res; + u_int val; + struct ifreq ifr; + kvm_t *kvm; + char errbuf[_POSIX2_LINE_MAX]; + struct ifnet_head ifh; + struct ifnet *ifp; + struct ifaddr *ifap = 0; + struct sockaddr_dl *sdlp; + int sdllen; + + bpf = open(BPFDEV, O_RDWR, 0); + if (bpf < 0) { + warn("open %s", BPFDEV); + return 0; + } + + val = MAXPKT; + res = ioctl(bpf, BIOCSBLEN, &val); + if (res < 0) { + warn("ioctl BIOCSBLEN"); + return 0; + } + + val = 1; + res = ioctl(bpf, BIOCIMMEDIATE, &val); + if (res < 0) { + warn("ioctl BIOCIMMEDIATE"); + return 0; + } + + val = 1; + res = ioctl(bpf, FIONBIO, &val); + if (res < 0) { + warn("ioctl FIONBIO"); + return 0; + } + + memcpy(ifr.ifr_name, BPF_IFNAME, IFNAMSIZ); + res = ioctl(bpf, BIOCSETIF, &ifr); + if (res < 0) { + warn("ioctl BIOCSETIF %s", BPF_IFNAME); + return 0; + } + + kvm = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); + if (!kvm) { + warnx(errbuf); + return 0; + } + if (kvm_nlist(kvm, nl) < 0) { + warnx("nlist failed (%s)", kvm_geterr(kvm)); + kvm_close(kvm); + return 0; + } + + kvm_read(kvm, nl[0].n_value, &ifh, sizeof(struct ifnet_head)); + ifp = TAILQ_FIRST(&ifh); + while (ifp) { + struct ifnet ifnet; + kvm_read(kvm, (u_long)ifp, &ifnet, sizeof(struct ifnet)); + if (!strcmp(ifnet.if_xname, BPF_IFNAME)) { + ifap = IFADDR_FIRST(&ifnet); + break; + } + ifp = IFNET_NEXT(&ifnet); + } + if (!ifp) { + warnx("interface not found"); + kvm_close(kvm); + return 0; + } + +#define _offsetof(t, m) ((int)((void *)&((t *)0)->m)) + sdllen = _offsetof(struct sockaddr_dl, + sdl_data[0]) + strlen(BPF_IFNAME) + 6; + sdlp = malloc(sdllen); + + while (ifap) { + struct ifaddr ifaddr; + kvm_read(kvm, (u_long)ifap, &ifaddr, sizeof(struct ifaddr)); + kvm_read(kvm, (u_long)ifaddr.ifa_addr, sdlp, sdllen); + if (sdlp->sdl_family == AF_LINK) { + memcpy(ha, CLLADDR(sdlp), 6); + break; + } + ifap = IFADDR_NEXT(&ifaddr); + } + free(sdlp); + kvm_close(kvm); + if (!ifap) { + warnx("interface hw addr not found"); + return 0; + } + return 1; +} + +void +EtherStop(void) +{ + + if (bpf != -1) + close(bpf); +} + +int +EtherSend(char *pkt, int len) +{ + + if (write(bpf, pkt, len) != len) { + warn("EtherSend"); + return -1; + } + return len; +} + +static union { + struct bpf_hdr h; + u_char buf[MAXPKT]; +} rbuf; + +int +EtherReceive(char *pkt, int maxlen) +{ + int res; + + res = read(bpf, &rbuf, MAXPKT); + if (res > 0) { +#if 0 + int i; + fprintf(stderr, "got packet, len=%d\n", rbuf.h.bh_caplen); + if (rbuf.h.bh_caplen < rbuf.h.bh_datalen) + printf("(truncated)\n"); + for (i = 0; i < 20; i++) + fprintf(stderr, "%02x ", rbuf.buf[rbuf.h.bh_hdrlen + i]); + fprintf(stderr, "\n"); +#endif + if (rbuf.h.bh_caplen > maxlen) + return 0; + memcpy(pkt, &rbuf.buf[rbuf.h.bh_hdrlen], rbuf.h.bh_caplen); + return rbuf.h.bh_caplen; + } + + return 0; +} diff --git a/sys/arch/i386/stand/lib/test/pci_user.c b/sys/arch/i386/stand/lib/test/pci_user.c new file mode 100644 index 000000000..57a3c7bbf --- /dev/null +++ b/sys/arch/i386/stand/lib/test/pci_user.c @@ -0,0 +1,101 @@ +/* $NetBSD: pci_user.c,v 1.4 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sanamespace.h" + +#include +#include + +#include + +extern int mapio(void); + +/* + * Replacement for i386/stand/lib/biospci.c. + * Very simple functions to access PCI config space from + * userland. Works with configuration mode 1 only, can + * only access bus number 0. + */ + +#define PCI_MODE1_ENABLE 0x80000000UL +#define PCI_MODE1_ADDRESS_REG 0x0cf8 +#define PCI_MODE1_DATA_REG 0x0cfc + +static int +maketag(int bus, int dev, int fcn) +{ + + return PCI_MODE1_ENABLE | + (bus << 16) | (dev << 11) | (fcn << 8); +} + +int +pcicheck(void) +{ + + return mapio() ? -1 : 0; +} + +int +pcifinddev(int vid, int did, pcihdl_t *handle) +{ + int i; + + for (i = 0; i < 32; i++) { + pcihdl_t h; + int id; + h = maketag(0, i, 0); + pcicfgread(&h, 0, &id); + if (id == (vid | (did << 16))) { + *handle = h; + return 0; + } + } + return -1; +} + +int +pcicfgread(pcihdl_t *handle, int off, int *val) +{ + int data; + + outl(PCI_MODE1_ADDRESS_REG, *handle | off); + data = inl(PCI_MODE1_DATA_REG); + outl(PCI_MODE1_ADDRESS_REG, 0); + *val = data; + return 0; +} + +int +pcicfgwrite(pcihdl_t *handle, int off, int val) +{ + outl(PCI_MODE1_ADDRESS_REG, *handle | off); + outl(PCI_MODE1_DATA_REG, val); + outl(PCI_MODE1_ADDRESS_REG, 0); + return 0; +} diff --git a/sys/arch/i386/stand/lib/test/sanamespace.h b/sys/arch/i386/stand/lib/test/sanamespace.h new file mode 100644 index 000000000..41264a58a --- /dev/null +++ b/sys/arch/i386/stand/lib/test/sanamespace.h @@ -0,0 +1,20 @@ +/* $NetBSD: sanamespace.h,v 1.1 1998/05/15 17:07:16 drochner Exp $ */ + +/* take back the namespace mangling done by "Makefile.satest" */ + +#undef main +#undef exit +#undef free +#undef open +#undef close +#undef read +#undef write +#undef ioctl +#undef lseek +#undef printf +#undef sprintf +#undef vprintf +#undef putchar +#undef gets +#undef strerror +#undef errno diff --git a/sys/arch/i386/stand/lib/test/stand_user.c b/sys/arch/i386/stand/lib/test/stand_user.c new file mode 100644 index 000000000..c31f1d66b --- /dev/null +++ b/sys/arch/i386/stand/lib/test/stand_user.c @@ -0,0 +1,143 @@ +/* $NetBSD: stand_user.c,v 1.6 2008/12/14 18:46:33 christos Exp $ */ + +/* + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "sanamespace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Harness for test of standalone code in user space. + * XXX Requires silly namespace games. + */ + +#ifndef HEAPSIZE +#define HEAPSIZE (128*1024) +#endif + +int samain(void); + +int +main(void) +{ + char *h = malloc(HEAPSIZE); + setheap(h, h + HEAPSIZE); + + return samain(); +} + +void +_rtt(void) +{ + warnx("_rtt called"); + _exit(1); +} + +int +getsecs(void) +{ + struct timeval t; + gettimeofday(&t, 0); + return t.tv_sec; +} + +void +delay(int t) +{ + struct timeval to; + to.tv_sec = 0; + to.tv_usec = t; + select(0, 0, 0, 0, &to); +} + +/* make output appear unbuffered */ +void +saputchar(int c) +{ + putchar(c); + fflush(stdout); +} + +/* + * some functions to get access to the hardware + */ + +static int memfd, memcnt; + +void * +mapmem(int offset, int len) +{ + void *base; + + if (memcnt == 0) + memfd = open("/dev/mem", O_RDWR, 0); + if (memfd < 0) { + warn("open /dev/mem"); + return 0; + } + base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, + memfd, offset); + if (base == (void *)-1) { + warn("mmap %x-%x", offset, offset + len - 1); + return 0; + } + memcnt++; + return base; +} + +void +unmapmem(void *addr, int len) +{ + + munmap(addr, len); + memcnt--; + if (memcnt == 0) + close(memfd); +} + +int +mapio(void) +{ + int res; + + res = i386_iopl(1); + if (res) + warn("i386_iopl"); + return res; +} + +int ourseg = 12345; diff --git a/sys/arch/i386/stand/lib/vbe.c b/sys/arch/i386/stand/lib/vbe.c new file mode 100644 index 000000000..e2141bf44 --- /dev/null +++ b/sys/arch/i386/stand/lib/vbe.c @@ -0,0 +1,419 @@ +/* $NetBSD: vbe.c,v 1.7 2011/02/09 04:37:54 jmcneill Exp $ */ + +/*- + * Copyright (c) 2009 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 +#include +#include +#include "libi386.h" +#include "vbe.h" + +extern const uint8_t rasops_cmap[]; +static uint8_t *vbe_edid = NULL; +static int vbe_edid_valid = 0; + +static struct _vbestate { + int available; + int modenum; +} vbestate; + +static int +vbe_mode_is_supported(struct modeinfoblock *mi) +{ + if ((mi->ModeAttributes & 0x01) == 0) + return 0; /* mode not supported by hardware */ + if ((mi->ModeAttributes & 0x08) == 0) + return 0; /* linear fb not available */ + if ((mi->ModeAttributes & 0x10) == 0) + return 0; /* text mode */ + if (mi->NumberOfPlanes != 1) + return 0; /* planar mode not supported */ + if (mi->MemoryModel != 0x04 /* Packed pixel */ && + mi->MemoryModel != 0x06 /* Direct Color */) + return 0; /* unsupported pixel format */ + return 1; +} + +static bool +vbe_check(void) +{ + if (!vbestate.available) { + printf("VBE not available\n"); + return false; + } + return true; +} + +void +vbe_init(void) +{ + struct vbeinfoblock vbe; + + memset(&vbe, 0, sizeof(vbe)); + memcpy(vbe.VbeSignature, "VBE2", 4); + if (biosvbe_info(&vbe) != 0x004f) + return; + if (memcmp(vbe.VbeSignature, "VESA", 4) != 0) + return; + + vbestate.available = 1; + vbestate.modenum = 0; +} + +int +vbe_available(void) +{ + return vbestate.available; +} + +int +vbe_set_palette(const uint8_t *cmap, int slot) +{ + struct paletteentry pe; + int ret; + + if (!vbe_check()) + return 1; + + pe.Blue = cmap[2] >> 2; + pe.Green = cmap[1] >> 2; + pe.Red = cmap[0] >> 2; + pe.Alignment = 0; + + ret = biosvbe_palette_data(0x0600, slot, &pe); + + return ret == 0x004f ? 0 : 1; +} + +int +vbe_set_mode(int modenum) +{ + struct modeinfoblock mi; + struct btinfo_framebuffer fb; + int ret, i; + + if (!vbe_check()) + return 1; + + ret = biosvbe_get_mode_info(modenum, &mi); + if (ret != 0x004f) { + printf("mode 0x%x invalid\n", modenum); + return 1; + } + + if (!vbe_mode_is_supported(&mi)) { + printf("mode 0x%x not supported\n", modenum); + return 1; + } + + ret = biosvbe_set_mode(modenum); + if (ret != 0x004f) { + printf("mode 0x%x could not be set\n", modenum); + return 1; + } + + /* Setup palette for packed pixel mode */ + if (mi.MemoryModel == 0x04) + for (i = 0; i < 256; i++) + vbe_set_palette(&rasops_cmap[i * 3], i); + + fb.physaddr = (uint64_t)mi.PhysBasePtr & 0xffffffff; + fb.width = mi.XResolution; + fb.height = mi.YResolution; + fb.stride = mi.BytesPerScanLine; + fb.depth = mi.BitsPerPixel; + fb.flags = 0; + fb.rnum = mi.RedMaskSize; + fb.rpos = mi.RedFieldPosition; + fb.gnum = mi.GreenMaskSize; + fb.gpos = mi.GreenFieldPosition; + fb.bnum = mi.BlueMaskSize; + fb.bpos = mi.BlueFieldPosition; + fb.vbemode = modenum; + + framebuffer_configure(&fb); + + return 0; +} + +int +vbe_commit(void) +{ + int ret = 1; + + if (vbestate.modenum > 0) { + ret = vbe_set_mode(vbestate.modenum); + if (ret) { + printf("WARNING: failed to set VBE mode 0x%x\n", + vbestate.modenum); + wait_sec(5); + } + } + return ret; +} + +static void * +vbe_farptr(uint32_t farptr) +{ + return VBEPHYPTR((((farptr & 0xffff0000) >> 12) + (farptr & 0xffff))); +} + +static int +vbe_parse_mode_str(char *str, int *x, int *y, int *depth) +{ + char *p; + + p = str; + *x = strtoul(p, NULL, 0); + if (*x == 0) + return 0; + p = strchr(p, 'x'); + if (!p) + return 0; + ++p; + *y = strtoul(p, NULL, 0); + if (*y == 0) + return 0; + p = strchr(p, 'x'); + if (!p) + *depth = 8; + else { + ++p; + *depth = strtoul(p, NULL, 0); + if (*depth == 0) + return 0; + } + + return 1; +} + +static int +vbe_find_mode_xyd(int x, int y, int depth) +{ + struct vbeinfoblock vbe; + struct modeinfoblock mi; + uint32_t farptr; + uint16_t mode; + int safety = 0; + + memset(&vbe, 0, sizeof(vbe)); + memcpy(vbe.VbeSignature, "VBE2", 4); + if (biosvbe_info(&vbe) != 0x004f) + return 0; + if (memcmp(vbe.VbeSignature, "VESA", 4) != 0) + return 0; + farptr = vbe.VideoModePtr; + if (farptr == 0) + return 0; + + while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) { + safety++; + farptr += 2; + if (safety == 100) + return 0; + if (biosvbe_get_mode_info(mode, &mi) != 0x004f) + continue; + /* we only care about linear modes here */ + if (vbe_mode_is_supported(&mi) == 0) + continue; + safety = 0; + if (mi.XResolution == x && + mi.YResolution == y && + mi.BitsPerPixel == depth) + return mode; + } + + return 0; +} + +static int +vbe_find_mode(char *str) +{ + int x, y, depth; + + if (!vbe_parse_mode_str(str, &x, &y, &depth)) + return 0; + + return vbe_find_mode_xyd(x, y, depth); +} + +static void +vbe_dump_mode(int modenum, struct modeinfoblock *mi) +{ + printf("0x%x=%dx%dx%d", modenum, + mi->XResolution, mi->YResolution, mi->BitsPerPixel); +} + +static int +vbe_get_edid(int *pwidth, int *pheight) +{ + const uint8_t magic[] = EDID_MAGIC; + int ddc_caps, ret; + + ddc_caps = biosvbe_ddc_caps(); + if (ddc_caps == 0) { + return 1; + } + + if (vbe_edid == NULL) { + vbe_edid = alloc(128); + } + if (vbe_edid_valid == 0) { + ret = biosvbe_ddc_read_edid(0, vbe_edid); + if (ret != 0x004f) + return 1; + if (memcmp(vbe_edid, magic, sizeof(magic)) != 0) + return 1; + vbe_edid_valid = 1; + } + + *pwidth = vbe_edid[EDID_DESC_BLOCK + 2] | + (((int)vbe_edid[EDID_DESC_BLOCK + 4] & 0xf0) << 4); + *pheight = vbe_edid[EDID_DESC_BLOCK + 5] | + (((int)vbe_edid[EDID_DESC_BLOCK + 7] & 0xf0) << 4); + + return 0; +} + +void +vbe_modelist(void) +{ + struct vbeinfoblock vbe; + struct modeinfoblock mi; + uint32_t farptr; + uint16_t mode; + int nmodes = 0, safety = 0; + int ddc_caps, edid_width, edid_height; + + if (!vbe_check()) + return; + + ddc_caps = biosvbe_ddc_caps(); + if (ddc_caps & 3) { + printf("DDC"); + if (ddc_caps & 1) + printf(" [DDC1]"); + if (ddc_caps & 2) + printf(" [DDC2]"); + + if (vbe_get_edid(&edid_width, &edid_height) != 0) + printf(": no EDID information\n"); + else + printf(": EDID %dx%d\n", edid_width, edid_height); + } + + printf("Modes: "); + memset(&vbe, 0, sizeof(vbe)); + memcpy(vbe.VbeSignature, "VBE2", 4); + if (biosvbe_info(&vbe) != 0x004f) + goto done; + if (memcmp(vbe.VbeSignature, "VESA", 4) != 0) + goto done; + farptr = vbe.VideoModePtr; + if (farptr == 0) + goto done; + + while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) { + safety++; + farptr += 2; + if (safety == 100) { + printf("[?] "); + break; + } + if (biosvbe_get_mode_info(mode, &mi) != 0x004f) + continue; + /* we only care about linear modes here */ + if (vbe_mode_is_supported(&mi) == 0) + continue; + safety = 0; + if (nmodes % 4 == 0) + printf("\n"); + else + printf(" "); + vbe_dump_mode(mode, &mi); + nmodes++; + } + +done: + if (nmodes == 0) + printf("none found"); + printf("\n"); +} + +void +command_vesa(char *cmd) +{ + char arg[20]; + int modenum, edid_width, edid_height; + + if (!vbe_check()) + return; + + strlcpy(arg, cmd, sizeof(arg)); + + if (strcmp(arg, "list") == 0) { + vbe_modelist(); + return; + } + + if (strcmp(arg, "disabled") == 0 || strcmp(arg, "off") == 0) { + vbestate.modenum = 0; + return; + } + + if (strcmp(arg, "enabled") == 0 || strcmp(arg, "on") == 0) { + if (vbe_get_edid(&edid_width, &edid_height) != 0) { + modenum = VBE_DEFAULT_MODE; + } else { + modenum = vbe_find_mode_xyd(edid_width, edid_height, 8); + if (modenum == 0) + modenum = VBE_DEFAULT_MODE; + } + } else if (strncmp(arg, "0x", 2) == 0) { + modenum = strtoul(arg, NULL, 0); + } else if (strchr(arg, 'x') != NULL) { + modenum = vbe_find_mode(arg); + if (modenum == 0) { + printf("mode %s not supported by firmware\n", arg); + return; + } + } else { + modenum = 0; + } + + if (modenum >= 0x100) { + vbestate.modenum = modenum; + return; + } + + printf("invalid flag, must be 'on', 'off', " + "a display mode, or a VBE mode number\n"); +} diff --git a/sys/arch/i386/stand/lib/vbe.h b/sys/arch/i386/stand/lib/vbe.h new file mode 100644 index 000000000..2476cbc13 --- /dev/null +++ b/sys/arch/i386/stand/lib/vbe.h @@ -0,0 +1,112 @@ +/* $NetBSD: vbe.h,v 1.3 2011/02/09 04:37:54 jmcneill Exp $ */ + +/*- + * Copyright (c) 2009 Jared D. McNeill + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define VBE_DEFAULT_MODE 0x101 /* 640x480x8 */ + +struct vbeinfoblock { + char VbeSignature[4]; + uint16_t VbeVersion; + uint32_t OemStringPtr; + uint32_t Capabilities; + uint32_t VideoModePtr; + uint16_t TotalMemory; + uint16_t OemSoftwareRev; + uint32_t OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr; + /* data area, in total max 512 bytes for VBE 2.0 */ + uint8_t Reserved[222]; + uint8_t OemData[256]; +} __packed; + +struct modeinfoblock { + /* Mandatory information for all VBE revisions */ + uint16_t ModeAttributes; + uint8_t WinAAttributes, WinBAttributes; + uint16_t WinGranularity, WinSize, WinASegment, WinBSegment; + uint32_t WinFuncPtr; + uint16_t BytesPerScanLine; + /* Mandatory information for VBE 1.2 and above */ + uint16_t XResolution, YResolution; + uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel; + uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages; + uint8_t Reserved1; + /* Direct Color fields + (required for direct/6 and YUV/7 memory models) */ + uint8_t RedMaskSize, RedFieldPosition; + uint8_t GreenMaskSize, GreenFieldPosition; + uint8_t BlueMaskSize, BlueFieldPosition; + uint8_t RsvdMaskSize, RsvdFieldPosition; + uint8_t DirectColorModeInfo; + /* Mandatory information for VBE 2.0 and above */ + uint32_t PhysBasePtr; + uint32_t OffScreenMemOffset; /* reserved in VBE 3.0 and above */ + uint16_t OffScreenMemSize; /* reserved in VBE 3.0 and above */ + + /* Mandatory information for VBE 3.0 and above */ + uint16_t LinBytesPerScanLine; + uint8_t BnkNumberOfImagePages; + uint8_t LinNumberOfImagePages; + uint8_t LinRedMaskSize, LinRedFieldPosition; + uint8_t LinGreenMaskSize, LinGreenFieldPosition; + uint8_t LinBlueMaskSize, LinBlueFieldPosition; + uint8_t LinRsvdMaskSize, LinRsvdFieldPosition; + uint32_t MaxPixelClock; + uint8_t Reserved4[189]; +} __packed; + +struct paletteentry { + uint8_t Blue; + uint8_t Green; + uint8_t Red; + uint8_t Alignment; +} __packed; + +/* EDID */ +#define EDID_MAGIC { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 } +#define EDID_DESC_BLOCK 0x36 + +/* low-level VBE calls, from biosvbe.S */ +int biosvbe_info(struct vbeinfoblock *); +int biosvbe_set_mode(int); +int biosvbe_get_mode_info(int, struct modeinfoblock *); +int biosvbe_palette_format(int); +int biosvbe_palette_data(int, int, struct paletteentry *); +int biosvbe_ddc_caps(void); +int biosvbe_ddc_read_edid(int, void *); + +/* high-level VBE helpers, from vbe.c */ +void vbe_init(void); +int vbe_commit(void); +int vbe_available(void); +int vbe_set_mode(int); +int vbe_set_palette(const uint8_t *, int); +void vbe_modelist(void); + +void command_vesa(char *); + +/* adjust physical address; boot code runs with %ds having a 64k offset */ +#define VBEPHYPTR(x) ((uint8_t *)((x) - (64 * 1024))) diff --git a/sys/lib/libkern/Makefile b/sys/lib/libkern/Makefile new file mode 100644 index 000000000..09e9b6aef --- /dev/null +++ b/sys/lib/libkern/Makefile @@ -0,0 +1,31 @@ +# $NetBSD: Makefile,v 1.95 2009/01/18 20:42:11 he Exp $ + +LIB= kern +NOPIC= # defined +LLIBS= # defined + +.include "Makefile.libkern" +.ifndef ARCHSUBDIR +.BEGIN: + @echo no ARCHSUBDIR for ${MACHINE_ARCH} nor ${MACHINE_CPU} + @false +.endif + +# only needed during build +libinstall:: + +.undef DESTDIR +.include + +lib${LIB}.o:: ${OBJS} + @echo building standard ${LIB} library + @rm -f lib${LIB}.o + @${LD} -r -o lib${LIB}.o `NM=${NM} ${LORDER} ${OBJS} | ${TSORT}` + +lib${LIB}.po:: ${POBJS} + @echo building profiled ${LIB} library + @rm -f lib${LIB}.po + @${LD} -r -o lib${LIB}.po `NM=${NM} ${LORDER} ${POBJS} | ${TSORT}` + +showsources: ${SRCS} + @echo ${.ALLSRC} diff --git a/sys/lib/libkern/Makefile.inc b/sys/lib/libkern/Makefile.inc new file mode 100644 index 000000000..9fe2db2b9 --- /dev/null +++ b/sys/lib/libkern/Makefile.inc @@ -0,0 +1,93 @@ +# $NetBSD: Makefile.inc,v 1.40 2005/12/20 19:35:26 christos Exp $ +# +# Configuration variables (default values are below): +# +# S must be set to the top of the 'sys' tree. +# KERNDST may be set to the location of the directory where library +# objects are to be built. Defaults to ${.OBJDIR}/lib/kern. +# KERN_AS may be set to 'obj' to build a object from the library's +# object files. (Otherwise, a library will be built.) +# Defaults to 'library'. +# KERNMISCCPPFLAGS +# Miscellaneous cpp flags to be passed to the library's Makefile +# when building. +# KERNMISCMAKEFLAGS +# Miscellaneous flags to be passed to the library's Makefile when +# building. See library's Makefile for more details about +# supported flags and their default values. + +# Default values: +KERNDST?= ${.OBJDIR}/lib/kern +KERN_AS?= library +KERNDOTDIR?= ../../. + +KERNDIR= ${S:S@^.@${KERNDOTDIR}@:Q}/lib/libkern +.if (${KERN_AS} == "obj") +KERNLIB= ${KERNDST}/libkern.o +KERNLIB_PROF= ${KERNDST}/libkern.po +.else +KERNLIB= ${KERNDST}/libkern.a +KERNLIB_PROF= ${KERNDST}/libkern_p.a +.endif + +LIBKERNLNBN= llib-lkern.ln +KERNLIBLN= ${KERNDST}/${LIBKERNLNBN} + +KERNMAKE= \ + cd ${KERNDST} && ${MAKE} -f ${KERNDIR:Q}/Makefile \ + KERNDIR=${KERNDIR:Q} \ + CC=${CC:Q} CFLAGS=${CFLAGS:Q} \ + AS=${AS:Q} AFLAGS=${AFLAGS:Q} \ + LORDER=${LORDER:Q} \ + TSORT=${TSORT:Q} \ + LD=${LD:Q} STRIP=${STRIP:Q} \ + AR=${AR:Q} NM=${NM:Q} \ + RANLIB=${RANLIB:Q} SIZE=${SIZE:Q} \ + MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \ + KERNCPPFLAGS=${CPPFLAGS:S@^-I.@-I${KERNDOTDIR}@g:Q} \ + KERNMISCCPPFLAGS=${KERNMISCCPPFLAGS:Q} \ + LINTFLAGS=${KERNLINTFLAGS:Q} \ + ${KERNMISCMAKEFLAGS} + +${KERNLIB}: .NOTMAIN .MAKE __always_make_kernlib + @echo making sure the kern library is up to date... +.if (${KERN_AS} == "library") + @${KERNMAKE} libkern.a +.else + @${KERNMAKE} libkern.o +.endif + +${KERNLIB_PROF}: .NOTMAIN .MAKE __always_make_kernlib + @echo making sure the profiled kern library is up to date... +.if (${KERN_AS} == "library") + @${KERNMAKE} libkern_p.a +.else + @${KERNMAKE} libkern.po +.endif + +${KERNLIBLN}: .NOTMAIN .MAKE __always_make_kernlib + @echo making sure the kern lint library is up to date... + @${KERNMAKE} ${LIBKERNLNBN} + +clean: .NOTMAIN cleankernlib +cleankernlib: .NOTMAIN + @echo cleaning the kern library objects + @if [ -d "${KERNDST}" ]; then ${KERNMAKE} clean; fi + +cleandir distclean: .NOTMAIN cleandirkernlib +cleandirkernlib: .NOTMAIN + @echo cleandiring the kern library objects + @if [ -d "${KERNDST}" ]; then ${KERNMAKE} cleandir; fi + +dependall depend: .NOTMAIN dependkernlib +dependkernlib: .NOTMAIN .MAKE __always_make_kernlib + @echo depending the kern library objects + @${KERNMAKE} depend + +__always_make_kernlib: .NOTMAIN + @(mkdir -p ${KERNDST}) + +.PHONY: __always_make_kernlib +.PHONY: cleankernlib cleandirkernlib dependkernlib + +.include "${.PARSEDIR}/../../../common/lib/libc/Makefile.inc" diff --git a/sys/lib/libkern/Makefile.libkern b/sys/lib/libkern/Makefile.libkern new file mode 100644 index 000000000..e15c16ca8 --- /dev/null +++ b/sys/lib/libkern/Makefile.libkern @@ -0,0 +1,108 @@ +# $NetBSD: Makefile.libkern,v 1.15 2011/11/19 22:51:25 tls Exp $ + +# +# Variable definitions for libkern. +# +# Before including this, you _must_ set +# KERNDIR: location of sys/lib/libkern +# +# You *may* set: +# LIBKERN_ARCH: architecture subdir to be used +# KERNCPPFLAGS: see Makefile.inc +# KERNMISCCPPFLAGS: see Makefile.inc +# + +.include + +.if defined(LIBKERN_ARCH) && !empty(LIBKERN_ARCH) && \ + exists(${KERNDIR}/arch/${LIBKERN_ARCH}) +ARCHSUBDIR= ${LIBKERN_ARCH} +.elif defined(MACHINE_ARCH) && !empty(MACHINE_ARCH) && \ + exists(${KERNDIR}/arch/${MACHINE_ARCH}) +ARCHSUBDIR= ${MACHINE_ARCH} +.elif defined(MACHINE_CPU) && !empty(MACHINE_CPU) && \ + exists(${KERNDIR}/arch/${MACHINE_CPU}) +ARCHSUBDIR= ${MACHINE_CPU} +.endif + +M= ${KERNDIR}/arch/${ARCHSUBDIR} + +CPPFLAGS+= -I$M ${KERNCPPFLAGS} ${KERNMISCCPPFLAGS} + +.include "${.PARSEDIR}/../../../common/lib/libc/Makefile.inc" +.include "${.PARSEDIR}/../../../common/lib/libutil/Makefile.inc" +.include "${.PARSEDIR}/../../../common/lib/libprop/Makefile.inc" +.include "${.PARSEDIR}/../../../common/lib/libppath/Makefile.inc" +.include "${.PARSEDIR}/../../../common/lib/libquota/Makefile.inc" + +CPPFLAGS+= -I${KERNDIR}/../../../common/include + +.PATH.c: ${KERNDIR} +.if exists ($M/Makefile.inc) +.PATH.c: $M +.PATH.S: $M +.include "$M/Makefile.inc" +.endif + +.if (${MACHINE_ARCH} != "alpha") && \ + (${MACHINE_ARCH} != "mips64eb" || !empty(CFLAGS:M-mabi=32)) && \ + (${MACHINE_ARCH} != "mips64el" || !empty(CFLAGS:M-mabi=32)) && \ + (${MACHINE_ARCH} != "powerpc64") && \ + (${MACHINE_ARCH} != "sparc64") && \ + (${MACHINE_ARCH} != "x86_64" || !empty(CFLAGS:M-m32)) +# Quad support +SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \ + lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \ + subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c +.endif + +# Other stuff +SRCS+= kern_assert.c __main.c +SRCS+= __cmsg_alignbytes.c cpuset.c inet_addr.c intoa.c +.if empty(SRCS:Mbyte_swap_8.*) +SRCS+= bswap64.c +.endif +SRCS+= md4c.c md5c.c rmd160.c sha1.c sha2.c +SRCS+= pmatch.c arc4random.c bcd.c mcount.c mertwist.c crc32.c + +SRCS+= ppath_kmem_alloc.c + +SRCS+= strsep.c strstr.c +SRCS+= strlcpy.c strlcat.c + +SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c +SRCS+= memcpy.c memmove.c +SRCS+= strchr.c strrchr.c +SRCS+= memcmp.c +.if empty(SRCS:Mmemset2.*) +SRCS+= memset.c +.endif +SRCS+= popcount32.c popcount64.c +SRCS+= strtoul.c strtoll.c strtoull.c strtoumax.c + +SRCS+= scanc.c skpc.c +SRCS+= random.c +SRCS+= rngtest.c + +SRCS+= memchr.c +SRCS+= strcat.c strcmp.c strcpy.c strlen.c +SRCS+= strncmp.c strncpy.c +SRCS+= strcasecmp.c strncasecmp.c + +SRCS+= xlat_mbr_fstype.c + +SRCS+= heapsort.c ptree.c rb.c + +# Files to clean up +CLEANFILES+= lib${LIB}.o lib${LIB}.po + +# Remove from SRCS the .c files for any .S files added by the MD makefiles, +# also remove from SRCS the .c files for the .c files in NO_SRCS. +# (Unlike libc, we don't worry about lint) + +.for check_file in ${SRCS:M*.S} ${NO_SRCS} +unwanted_file := ${SRCS:M${check_file:.S=.c}} +.if "${unwanted_file}" != "" +SRCS := ${SRCS:N${unwanted_file}} +.endif +.endfor diff --git a/sys/lib/libkern/__main.c b/sys/lib/libkern/__main.c new file mode 100644 index 000000000..fc0359cc2 --- /dev/null +++ b/sys/lib/libkern/__main.c @@ -0,0 +1,40 @@ +/* $NetBSD: __main.c,v 1.6 2009/03/15 21:33:51 cegger Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void __main(void); + +void +__main(void) +{ +} diff --git a/sys/lib/libkern/arc4random.c b/sys/lib/libkern/arc4random.c new file mode 100644 index 000000000..279c01648 --- /dev/null +++ b/sys/lib/libkern/arc4random.c @@ -0,0 +1,327 @@ +/* $NetBSD: arc4random.c,v 1.29 2011/11/29 13:16:27 drochner Exp $ */ + +/*- + * Copyright (c) 2002, 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Thor Lancelot Simon. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * THE BEER-WARE LICENSE + * + * 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 + +#ifdef _KERNEL +#include "rnd.h" +#else +#define NRND 0 +#endif + +#include +#include +#include +#ifdef _KERNEL +#include +#endif +#include + +#ifdef _KERNEL +#include +#include +#else +#define mutex_spin_enter(x) ; +#define mutex_spin_exit(x) ; +#define mutex_init(x, y, z) ; +#endif + +#include + +#if NRND > 0 +#include +#include + +static rndsink_t rs; + +#endif + +/* + * The best known attack that distinguishes RC4 output from a random + * bitstream requires 2^25 bytes. (see Paul and Preneel, Analysis of + * Non-fortuitous Predictive States of the RC4 Keystream Generator. + * INDOCRYPT 2003, pp52 – 67). + * + * However, we discard the first 1024 bytes of output, avoiding the + * biases detected in this paper. The best current attack that + * can distinguish this "RC4[drop]" output seems to be Fleuhrer & + * McGrew's attack which requires 2^30.6 bytes of output: + * Fluhrer and McGrew, Statistical Analysis of the Alleged RC4 + * Keystream Generator. FSE 2000, pp19 – 30 + * + * We begin trying to rekey at 2^24 bytes, and forcibly rekey at 2^29 bytes + * even if the resulting key cannot be guaranteed to have full entropy. + */ +#define ARC4_MAXBYTES (16 * 1024 * 1024) +#define ARC4_HARDMAX (512 * 1024 * 1024) +#define ARC4_RESEED_SECONDS 300 +#define ARC4_KEYBYTES 16 /* 128 bit key */ + +#ifdef _STANDALONE +#define time_uptime 1 /* XXX ugly! */ +#endif /* _STANDALONE */ + +static u_int8_t arc4_i, arc4_j; +static int arc4_initialized = 0; +static int arc4_numbytes = 0; +static u_int8_t arc4_sbox[256]; +static time_t arc4_nextreseed; + +#ifdef _KERNEL +kmutex_t arc4_mtx; +#endif + +static inline u_int8_t arc4_randbyte(void); +static inline void arc4randbytes_unlocked(void *, size_t); +void _arc4randbytes(void *, size_t); +uint32_t _arc4random(void); + +static inline void +arc4_swap(u_int8_t *a, u_int8_t *b) +{ + u_int8_t c; + + c = *a; + *a = *b; + *b = c; +} + +/* + * Stir our S-box. + */ +static void +arc4_randrekey(void *arg) +{ + u_int8_t key[256]; + int n, ask_for_more = 0; +#ifdef _KERNEL +#ifdef DIAGNOSTIC +#if 0 /* XXX rngtest_t is too large and could cause stack overflow */ + rngtest_t rt; +#endif +#endif +#endif +#if NRND > 0 + static int callback_pending; + int r; +#endif + + /* + * The first time through, we must take what we can get, + * so schedule ourselves for callback no matter what. + */ + if (__predict_true(arc4_initialized)) { + mutex_spin_enter(&arc4_mtx); + } +#if NRND > 0 /* XXX without rnd, we will key from the stack, ouch! */ + else { + ask_for_more = 1; + r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_ANY); + goto got_entropy; + } + + if (arg == NULL) { + if (callback_pending) { + if (arc4_numbytes > ARC4_HARDMAX) { + printf("arc4random: WARNING, hit 2^29 bytes, " + "forcibly rekeying.\n"); + r = rnd_extract_data(key, ARC4_KEYBYTES, + RND_EXTRACT_ANY); + rndsink_detach(&rs); + callback_pending = 0; + goto got_entropy; + } else { + mutex_spin_exit(&arc4_mtx); + return; + } + } + r = rnd_extract_data(key, ARC4_KEYBYTES, RND_EXTRACT_GOOD); + if (r < ARC4_KEYBYTES) { + ask_for_more = 1; + } + } else { + ask_for_more = 0; + callback_pending = 0; + if (rs.len != ARC4_KEYBYTES) { + panic("arc4_randrekey: rekey callback bad length"); + } + memcpy(key, rs.data, rs.len); + memset(rs.data, 0, rs.len); + } + +got_entropy: + + if (!ask_for_more) { + callback_pending = 0; + } else if (!callback_pending) { + callback_pending = 1; + strlcpy(rs.name, "arc4random", sizeof(rs.name)); + rs.cb = arc4_randrekey; + rs.arg = &rs; + rs.len = ARC4_KEYBYTES; + rndsink_attach(&rs); + } +#endif + /* + * If it's the first time, or we got a good key, actually rekey. + */ + if (!ask_for_more || !arc4_initialized) { + for (n = ARC4_KEYBYTES; n < sizeof(key); n++) + key[n] = key[n % ARC4_KEYBYTES]; + + for (n = 0; n < 256; n++) { + arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256; + arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]); + } + arc4_i = arc4_j; + + memset(key, 0, sizeof(key)); + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. (N = 256 in our case.) + */ + for (n = 0; n < 256 * 4; n++) + arc4_randbyte(); + + /* Reset for next reseed cycle. */ + arc4_nextreseed = time_uptime + ARC4_RESEED_SECONDS; + arc4_numbytes = 0; +#ifdef _KERNEL +#ifdef DIAGNOSTIC +#if 0 /* XXX rngtest_t is too large and could cause stack overflow */ + /* + * Perform the FIPS 140-2 statistical RNG test; warn if our + * output has such poor quality as to fail the test. + */ + arc4randbytes_unlocked(rt.rt_b, sizeof(rt.rt_b)); + strlcpy(rt.rt_name, "arc4random", sizeof(rt.rt_name)); + if (rngtest(&rt)) { + /* rngtest will scream to the console. */ + arc4_nextreseed = time_uptime; + arc4_numbytes = ARC4_MAXBYTES; + /* XXX should keep old context around, *NOT* use new */ + } +#endif +#endif +#endif + } + if (__predict_true(arc4_initialized)) { + mutex_spin_exit(&arc4_mtx); + } +} + +/* + * Initialize our S-box to its beginning defaults. + */ +static void +arc4_init(void) +{ + int n; + + mutex_init(&arc4_mtx, MUTEX_DEFAULT, IPL_VM); + arc4_i = arc4_j = 0; + for (n = 0; n < 256; n++) + arc4_sbox[n] = (u_int8_t) n; + + arc4_randrekey(NULL); + arc4_initialized = 1; +} + +/* + * Generate a random byte. + */ +static inline u_int8_t +arc4_randbyte(void) +{ + u_int8_t arc4_t; + + arc4_i = (arc4_i + 1) % 256; + arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256; + + arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]); + + arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256; + return arc4_sbox[arc4_t]; +} + +static inline void +arc4randbytes_unlocked(void *p, size_t len) +{ + u_int8_t *buf = (u_int8_t *)p; + size_t i; + + for (i = 0; i < len; buf[i] = arc4_randbyte(), i++) + continue; +} + +void +_arc4randbytes(void *p, size_t len) +{ + /* Initialize array if needed. */ + if (!arc4_initialized) { + arc4_init(); + /* avoid conditionalizing locking */ + return arc4randbytes_unlocked(p, len); + } + mutex_spin_enter(&arc4_mtx); + arc4randbytes_unlocked(p, len); + arc4_numbytes += len; + mutex_spin_exit(&arc4_mtx); + if ((arc4_numbytes > ARC4_MAXBYTES) || + (time_uptime > arc4_nextreseed)) { + arc4_randrekey(NULL); + } +} + +u_int32_t +_arc4random(void) +{ + u_int32_t ret; + u_int8_t *retc; + + retc = (u_int8_t *)&ret; + + _arc4randbytes(retc, sizeof(u_int32_t)); + return ret; +} diff --git a/sys/lib/libkern/arch/alpha/Makefile.inc b/sys/lib/libkern/arch/alpha/Makefile.inc new file mode 100644 index 000000000..9372ea4aa --- /dev/null +++ b/sys/lib/libkern/arch/alpha/Makefile.inc @@ -0,0 +1,54 @@ +# $NetBSD: Makefile.inc,v 1.28 2009/08/14 19:23:53 dsl Exp $ + +SRCS+= _mcount.S +SRCS+= byte_swap_2.S byte_swap_4.S +SRCS+= ffs.S +SRCS+= memcpy.S memmove.S + +SRCS+= softfloat.c + +# `source' files built from m4 source +SRCS+= __divqu.S __divq.S __divlu.S __divl.S +SRCS+= __remqu.S __remq.S __remlu.S __reml.S +CLEANFILES+= __divqu.S __divq.S __divlu.S __divl.S +CLEANFILES+= __remqu.S __remq.S __remlu.S __reml.S + +__divqu.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divqu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__divq.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divq')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__divlu.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divlu')define(OP,\`div')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__divl.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__divl')define(OP,\`div')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__remqu.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remqu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__remq.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remq')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,64)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__remlu.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__remlu')define(OP,\`rem')define(S,\`false')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +__reml.S: ${M}/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`__reml')define(OP,\`rem')define(S,\`true')"; \ + echo "define(WORDSIZE,32)"; cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} diff --git a/sys/lib/libkern/arch/alpha/divrem.m4 b/sys/lib/libkern/arch/alpha/divrem.m4 new file mode 100644 index 000000000..348bbfa75 --- /dev/null +++ b/sys/lib/libkern/arch/alpha/divrem.m4 @@ -0,0 +1,197 @@ +/* $NetBSD: divrem.m4,v 1.8 2005/12/11 12:24:42 christos Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Division and remainder. + * + * The use of m4 is modeled after the sparc code, but the algorithm is + * simple binary long division. + * + * Note that the loops could probably benefit from unrolling. + */ + +/* + * M4 Parameters + * NAME name of function to generate + * OP OP=div: t10 / t11 -> t12; OP=rem: t10 % t11 -> t12 + * S S=true: signed; S=false: unsigned + * WORDSIZE total number of bits + */ + +define(A, `t10') +define(B, `t11') +define(RESULT, `t12') + +define(BIT, `t0') +define(I, `t1') +define(CC, `t2') +define(T_0, `t3') +ifelse(S, `true', `define(NEG, `t4')') + +#include + +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< + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 + + .text +ENTRY(__clzdi2) + movs r3, r0 + movne r0, #31 + bne .L_clz + movs r3, r1 + movne r0, #63 + bne .L_clz + mov r0, #64 + RET +END(__clzdi2) + +ENTRY(__clzsi2) + movs r3, r0 + moveq r0, #32 + RETc(eq) + mov r0, #31 +.L_clz: + mvn r1, #0 +#ifndef __OPTIMIZE_SIZE__ + eor r1, r1, r1, lsr #16 /* 0xFFFFFFFF -> 0xFFFF0000 */ + ands r2, r3, r1 + eorne r0, r0, #16 + movne r3, r2 + eor r1, r1, r1, lsr #8 /* 0xFFFF0000 -> 0xFF00FF00 */ + ands r2, r3, r1 + eorne r0, r0, #8 + movne r3, r2 + eor r1, r1, r1, lsr #4 /* 0xFF00FF00 -> 0xF0F0F0F0 */ + ands r2, r3, r1 + eorne r0, r0, #4 + movne r3, r2 + eor r1, r1, r1, lsr #2 /* 0xF0F0F0F0 -> 0xCCCCCCCC */ + ands r2, r3, r1 + eorne r0, r0, #2 + movne r3, r2 + eor r1, r1, r1, lsr #1 /* 0xCCCCCCCC -> 0xAAAAAAAA */ + ands r2, r3, r1 + eorne r0, r0, #1 +#if 0 + teqeq r3, #0 + addeq r0, r0, #1 +#endif +#else + mov r2, #16 +1: eor r1, r1, r1, lsr r2 + ands ip, r3, r1 + movne r3, ip + eorne r0, r0, r2 + movs r2, r2, lsr #1 + bne 1b +#if 0 + teq r3, #0 + addeq r0, r0, #1 +#endif +#endif /* __OPTIMIZE_SIZE__ */ + RET +END(__clzsi2) diff --git a/sys/lib/libkern/arch/hppa/Makefile.inc b/sys/lib/libkern/arch/hppa/Makefile.inc new file mode 100644 index 000000000..570b29f8c --- /dev/null +++ b/sys/lib/libkern/arch/hppa/Makefile.inc @@ -0,0 +1,12 @@ +# $NetBSD: Makefile.inc,v 1.11 2009/09/22 09:57:16 pooka Exp $ + +SRCS+= milli.S +SRCS+= bcopy.S memcpy.S memmove.S + +# XXX: spcopy does not really belong in libkern in the first place +.ifndef RUMPKERNEL +SRCS+= spcopy.S +.endif + +SRCS+= ashrdi3.c divdi3.c +SRCS+= ffs.c bswap16.c bswap32.c diff --git a/sys/lib/libkern/arch/hppa/bcopy.S b/sys/lib/libkern/arch/hppa/bcopy.S new file mode 100644 index 000000000..98dc80c61 --- /dev/null +++ b/sys/lib/libkern/arch/hppa/bcopy.S @@ -0,0 +1,618 @@ +/* $NetBSD: bcopy.S,v 1.14 2011/01/31 12:10:58 skrll Exp $ */ + +/* + * Copyright (c) 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matthew Fredette. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copy routines for NetBSD/hppa. + */ + +#undef _LOCORE +#define _LOCORE /* XXX fredette - unfortunate */ + +#if defined(SPCOPY) && !defined(_STANDALONE) + +#include "opt_multiprocessor.h" + +#include + +#endif + +#include +#include +#include + +#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 +#include "assym.h" + +/* + * int spcopy(pa_space_t ssp, const void *src, pa_space_t dsp, void *dst, + * size_t len) + * + * We assume that the regions do not overlap. + */ +LEAF_ENTRY(spcopy) + + /* + * Setup the fault handler, which will fill in %ret0 if triggered. + */ + GET_CURLWP(%r31) +#ifdef DIAGNOSTIC + comb,<>,n %r0, %r31, Lspcopy_curlwp_ok + ldil L%panic, %r1 + ldil L%Lspcopy_curlwp_bad, %arg0 + ldo R%panic(%r1), %r1 + ldo R%Lspcopy_curlwp_bad(%arg0), %arg0 + .call + bv,n %r0(%r1) + nop +Lspcopy_curlwp_bad: + .asciz "spcopy: curlwp == NULL\n" + .align 8 +Lspcopy_curlwp_ok: +#endif /* DIAGNOSTIC */ + ldil L%spcopy_fault, %r1 + ldw L_PCB(%r31), %r31 + ldo R%spcopy_fault(%r1), %r1 + stw %r1, PCB_ONFAULT(%r31) + + /* Setup the space registers. */ + mfsp %sr2, %ret1 + mtsp %arg0, %sr1 + mtsp %arg2, %sr2 + + /* Get the len argument and do the copy. */ + ldw HPPA_FRAME_ARG(4)(%sp), %arg0 +#define _LABEL(l) __CONCAT(spcopy,l) + _COPY_FORWARD(%sr1,%arg1,%sr2,%arg3,%arg0) +_LABEL(_done): + + /* Return. */ + copy %r0, %ret0 +ALTENTRY(spcopy_fault) + stw %r0, PCB_ONFAULT(%r31) + bv %r0(%rp) + mtsp %ret1, %sr2 +EXIT(spcopy) +#endif /* SPCOPY && !_STANDALONE */ + +#ifdef MEMCPY +/* + * void *memcpy(void *restrict dst, const void *restrict src, size_t len); + * + * memcpy is specifically restricted to working on + * non-overlapping regions, so we can just copy forward. + */ +LEAF_ENTRY(memcpy) + copy %arg0, %ret0 +#define _LABEL(l) __CONCAT(memcpy,l) + _COPY_FORWARD(%sr0,%arg1,%sr0,%arg0,%arg2) +_LABEL(_done): + bv,n %r0(%rp) + nop +EXIT(memcpy) +#endif /* MEMCPY */ + +#ifdef BCOPY +/* + * void bcopy(const void *src, void *dst, size_t len); + */ +LEAF_ENTRY(bcopy) + copy %arg0, %r1 + copy %arg1, %arg0 + copy %r1, %arg1 + /* FALLTHROUGH */ +#define _LABEL_F(l) __CONCAT(bcopy_F,l) +#define _LABEL_R(l) __CONCAT(bcopy_R,l) +#endif + +#ifdef MEMMOVE +/* + * void *memmove(void *dst, const void *src, size_t len); + */ +LEAF_ENTRY(memmove) +#define _LABEL_F(l) __CONCAT(memmove_F,l) +#define _LABEL_R(l) __CONCAT(memmove_R,l) + copy %arg0, %ret0 +#endif /* MEMMOVE */ + +#if defined(BCOPY) || defined(MEMMOVE) + + /* + * If src >= dst or src + len <= dst, we copy + * forward, else we copy in reverse. + */ + add %arg1, %arg2, %r1 + comb,>>=,n %arg1, %arg0, 0 + comb,>>,n %r1, %arg0, _LABEL_R(_go) + +#define _LABEL _LABEL_F + _COPY_FORWARD(%sr0,%arg1,%sr0,%arg0,%arg2) +#undef _LABEL + +_LABEL_R(_go): +#define _LABEL _LABEL_R + _COPY_REVERSE(%sr0,%arg1,%sr0,%arg0,%arg2) +#undef _LABEL + +_LABEL_F(_done): +_LABEL_R(_done): + bv,n %r0(%rp) + nop +#ifdef BCOPY +EXIT(bcopy) +#else +EXIT(memmove) +#endif +#endif /* BCOPY || MEMMOVE */ diff --git a/sys/lib/libkern/arch/hppa/memcpy.S b/sys/lib/libkern/arch/hppa/memcpy.S new file mode 100644 index 000000000..edb220438 --- /dev/null +++ b/sys/lib/libkern/arch/hppa/memcpy.S @@ -0,0 +1,4 @@ +/* $NetBSD: memcpy.S,v 1.1 2002/06/06 20:03:38 fredette Exp $ */ + +#define MEMCPY +#include "bcopy.S" diff --git a/sys/lib/libkern/arch/hppa/memmove.S b/sys/lib/libkern/arch/hppa/memmove.S new file mode 100644 index 000000000..24a2872a5 --- /dev/null +++ b/sys/lib/libkern/arch/hppa/memmove.S @@ -0,0 +1,4 @@ +/* $NetBSD: memmove.S,v 1.1 2002/06/06 20:03:38 fredette Exp $ */ + +#define MEMMOVE +#include "bcopy.S" diff --git a/sys/lib/libkern/arch/hppa/milli.S b/sys/lib/libkern/arch/hppa/milli.S new file mode 100644 index 000000000..adc7ca13c --- /dev/null +++ b/sys/lib/libkern/arch/hppa/milli.S @@ -0,0 +1,1814 @@ +; $NetBSD: milli.S,v 1.1 2002/06/06 20:03:39 fredette Exp $ +; +; $OpenBSD: milli.S,v 1.5 2001/03/29 04:08:20 mickey Exp $ +; +; (c) Copyright 1986 HEWLETT-PACKARD COMPANY +; +; To anyone who acknowledges that this file is provided "AS IS" +; without any express or implied warranty: +; permission to use, copy, modify, and distribute this file +; for any purpose is hereby granted without fee, provided that +; the above copyright notice and this notice appears in all +; copies, and that the name of Hewlett-Packard Company not be +; used in advertising or publicity pertaining to distribution +; of the software without specific, written prior permission. +; Hewlett-Packard Company makes no representations about the +; suitability of this software for any purpose. +; + +; Standard Hardware Register Definitions for Use with Assembler +; version A.08.06 +; - fr16-31 added at Utah +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; Hardware General Registers +r0: .equ 0 + +r1: .equ 1 + +r2: .equ 2 + +r3: .equ 3 + +r4: .equ 4 + +r5: .equ 5 + +r6: .equ 6 + +r7: .equ 7 + +r8: .equ 8 + +r9: .equ 9 + +r10: .equ 10 + +r11: .equ 11 + +r12: .equ 12 + +r13: .equ 13 + +r14: .equ 14 + +r15: .equ 15 + +r16: .equ 16 + +r17: .equ 17 + +r18: .equ 18 + +r19: .equ 19 + +r20: .equ 20 + +r21: .equ 21 + +r22: .equ 22 + +r23: .equ 23 + +r24: .equ 24 + +r25: .equ 25 + +r26: .equ 26 + +r27: .equ 27 + +r28: .equ 28 + +r29: .equ 29 + +r30: .equ 30 + +r31: .equ 31 + +; Hardware Space Registers +sr0: .equ 0 + +sr1: .equ 1 + +sr2: .equ 2 + +sr3: .equ 3 + +sr4: .equ 4 + +sr5: .equ 5 + +sr6: .equ 6 + +sr7: .equ 7 + +; Hardware Floating Point Registers +fr0: .equ 0 + +fr1: .equ 1 + +fr2: .equ 2 + +fr3: .equ 3 + +fr4: .equ 4 + +fr5: .equ 5 + +fr6: .equ 6 + +fr7: .equ 7 + +fr8: .equ 8 + +fr9: .equ 9 + +fr10: .equ 10 + +fr11: .equ 11 + +fr12: .equ 12 + +fr13: .equ 13 + +fr14: .equ 14 + +fr15: .equ 15 + +fr16: .equ 16 + +fr17: .equ 17 + +fr18: .equ 18 + +fr19: .equ 19 + +fr20: .equ 20 + +fr21: .equ 21 + +fr22: .equ 22 + +fr23: .equ 23 + +fr24: .equ 24 + +fr25: .equ 25 + +fr26: .equ 26 + +fr27: .equ 27 + +fr28: .equ 28 + +fr29: .equ 29 + +fr30: .equ 30 + +fr31: .equ 31 + +; Hardware Control Registers +cr0: .equ 0 + +rctr: .equ 0 ; Recovery Counter Register + +cr8: .equ 8 ; Protection ID 1 + +pidr1: .equ 8 + +cr9: .equ 9 ; Protection ID 2 + +pidr2: .equ 9 + +cr10: .equ 10 + +ccr: .equ 10 ; Coprocessor Confiquration Register + +cr11: .equ 11 + +sar: .equ 11 ; Shift Amount Register + +cr12: .equ 12 + +pidr3: .equ 12 ; Protection ID 3 + +cr13: .equ 13 + +pidr4: .equ 13 ; Protection ID 4 + +cr14: .equ 14 + +iva: .equ 14 ; Interrupt Vector Address + +cr15: .equ 15 + +eiem: .equ 15 ; External Interrupt Enable Mask + +cr16: .equ 16 + +itmr: .equ 16 ; Interval Timer + +cr17: .equ 17 + +pcsq: .equ 17 ; Program Counter Space queue + +cr18: .equ 18 + +pcoq: .equ 18 ; Program Counter Offset queue + +cr19: .equ 19 + +iir: .equ 19 ; Interruption Instruction Register + +cr20: .equ 20 + +isr: .equ 20 ; Interruption Space Register + +cr21: .equ 21 + +ior: .equ 21 ; Interruption Offset Register + +cr22: .equ 22 + +ipsw: .equ 22 ; Interrpution Processor Status Word + +cr23: .equ 23 + +eirr: .equ 23 ; External Interrupt Request + +cr24: .equ 24 + +ppda: .equ 24 ; Physcial Page Directory Address + +tr0: .equ 24 ; Temporary register 0 + +cr25: .equ 25 + +hta: .equ 25 ; Hash Table Address + +tr1: .equ 25 ; Temporary register 1 + +cr26: .equ 26 + +tr2: .equ 26 ; Temporary register 2 + +cr27: .equ 27 + +tr3: .equ 27 ; Temporary register 3 + +cr28: .equ 28 + +tr4: .equ 28 ; Temporary register 4 + +cr29: .equ 29 + +tr5: .equ 29 ; Temporary register 5 + +cr30: .equ 30 + +tr6: .equ 30 ; Temporary register 6 + +cr31: .equ 31 + +tr7: .equ 31 ; Temporary register 7 + +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; Procedure Call Convention ~ +; Register Definitions for Use with Assembler ~ +; version A.08.06 ~ +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; Software Architecture General Registers +rp: .equ r2 ; return pointer + +mrp: .equ r31 ; millicode return pointer + +ret0: .equ r28 ; return value + +ret1: .equ r29 ; return value (high part of double) + +sl: .equ r29 ; static link + +sp: .equ r30 ; stack pointer + +dp: .equ r27 ; data pointer + +arg0: .equ r26 ; argument + +arg1: .equ r25 ; argument or high part of double argument + +arg2: .equ r24 ; argument + +arg3: .equ r23 ; argument or high part of double argument + +;_____________________________________________________________________________ +; Software Architecture Space Registers +; sr0 ; return link form BLE +sret: .equ sr1 ; return value + +sarg: .equ sr1 ; argument + +; sr4 ; PC SPACE tracker +; sr5 ; process private data +;_____________________________________________________________________________ +; Software Architecture Pseudo Registers +previous_sp: .equ 64 ; old stack pointer (locates previous frame) + +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +; Standard space and subspace definitions. version A.08.06 +; These are generally suitable for programs on HP_UX and HPE. +; Statements commented out are used when building such things as operating +; system kernels. +;;;;;;;;;;;;;;;; +; Additional code subspaces should have ALIGN=8 for an interspace BV +; and should have SORT=24. +; +; For an incomplete executable (program bound to shared libraries), +; sort keys $GLOBAL$ -1 and $GLOBAL$ -2 are reserved for the $DLT$ +; and $PLT$ subspaces respectively. +;;;;;;;;;;;;;;; + + .text + .EXPORT $$remI,millicode +; .IMPORT cerror +$$remI: + .PROC + .CALLINFO NO_CALLS + .ENTRY + addit,= 0,arg1,r0 + add,>= r0,arg0,ret1 + sub r0,ret1,ret1 + sub r0,arg1,r1 + ds r0,r1,r0 + or r0,r0,r1 + add ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + ds r1,arg1,r1 + addc ret1,ret1,ret1 + movb,>=,n r1,ret1,remI300 + add,< arg1,r0,r0 + add,tr r1,arg1,ret1 + sub r1,arg1,ret1 +remI300: add,>= arg0,r0,r0 + + sub r0,ret1,ret1 + bv r0(r31) + nop + .EXIT + .PROCEND + +bit1: .equ 1 + +bit30: .equ 30 +bit31: .equ 31 + +len2: .equ 2 + +len4: .equ 4 + +#if 0 +$$dyncall: + .proc + .callinfo NO_CALLS + .export $$dyncall,MILLICODE + + bb,>=,n 22,bit30,noshlibs + + depi 0,bit31,len2,22 + ldw 4(22),19 + ldw 0(22),22 +noshlibs: + ldsid (22),r1 + mtsp r1,sr0 + be 0(sr0,r22) + stw rp,-24(sp) + .procend +#endif + +$$sh_func_adrs: + .proc + .callinfo NO_CALLS + .export $$sh_func_adrs, millicode + ldo 0(r26),ret1 + dep r0,30,1,r26 + probew (r26),r31,r22 + extru,= r22,31,1,r22 + bv r0(r31) + ldws 0(r26),ret1 + .procend + +temp: .EQU r1 + +retreg: .EQU ret1 ; r29 + + .export $$divU,millicode + .import $$divU_3,millicode + .import $$divU_5,millicode + .import $$divU_6,millicode + .import $$divU_7,millicode + .import $$divU_9,millicode + .import $$divU_10,millicode + .import $$divU_12,millicode + .import $$divU_14,millicode + .import $$divU_15,millicode +$$divU: + .proc + .callinfo NO_CALLS +; The subtract is not nullified since it does no harm and can be used +; by the two cases that branch back to "normal". + comib,>= 15,arg1,special_divisor + sub r0,arg1,temp ; clear carry, negate the divisor + ds r0,temp,r0 ; set V-bit to 1 +normal: + add arg0,arg0,retreg ; shift msb bit into carry + ds r0,arg1,temp ; 1st divide step, if no carry + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 2nd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 3rd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 4th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 5th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 6th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 7th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 8th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 9th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 10th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 11th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 12th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 13th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 14th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 15th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 16th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 17th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 18th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 19th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 20th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 21st divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 22nd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 23rd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 24th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 25th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 26th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 27th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 28th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 29th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 30th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 31st divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 32nd divide step, + bv 0(r31) + addc retreg,retreg,retreg ; shift last retreg bit into retreg +;_____________________________________________________________________________ +; handle the cases where divisor is a small constant or has high bit on +special_divisor: + blr arg1,r0 + comib,>,n 0,arg1,big_divisor ; nullify previous instruction +zero_divisor: ; this label is here to provide external visibility + + addit,= 0,arg1,0 ; trap for zero dvr + nop + bv 0(r31) ; divisor == 1 + copy arg0,retreg + bv 0(r31) ; divisor == 2 + extru arg0,30,31,retreg + b,n $$divU_3 ; divisor == 3 + nop + bv 0(r31) ; divisor == 4 + extru arg0,29,30,retreg + b,n $$divU_5 ; divisor == 5 + nop + b,n $$divU_6 ; divisor == 6 + nop + b,n $$divU_7 ; divisor == 7 + nop + bv 0(r31) ; divisor == 8 + extru arg0,28,29,retreg + b,n $$divU_9 ; divisor == 9 + nop + b,n $$divU_10 ; divisor == 10 + nop + b normal ; divisor == 11 + ds r0,temp,r0 ; set V-bit to 1 + b,n $$divU_12 ; divisor == 12 + nop + b normal ; divisor == 13 + ds r0,temp,r0 ; set V-bit to 1 + b,n $$divU_14 ; divisor == 14 + nop + b,n $$divU_15 ; divisor == 15 + nop +;_____________________________________________________________________________ +; Handle the case where the high bit is on in the divisor. +; Compute: if( dividend>=divisor) quotient=1; else quotient=0; +; Note: dividend>==divisor iff dividend-divisor does not borrow +; and not borrow iff carry +big_divisor: + sub arg0,arg1,r0 + bv 0(r31) + addc r0,r0,retreg + .procend + .end + +t2: .EQU r1 + +; x2 .EQU arg0 ; r26 +t1: .EQU arg1 ; r25 + +; x1 .EQU ret1 ; r29 +;_____________________________________________________________________________ + +$$divide_by_constant: + .PROC + .CALLINFO NO_CALLS + .export $$divide_by_constant,millicode +; Provides a "nice" label for the code covered by the unwind descriptor +; for things like gprof. + +$$divI_2: + .EXPORT $$divI_2,MILLICODE + COMCLR,>= arg0,0,0 + ADDI 1,arg0,arg0 + bv 0(r31) + EXTRS arg0,30,31,ret1 + +$$divI_4: + .EXPORT $$divI_4,MILLICODE + COMCLR,>= arg0,0,0 + ADDI 3,arg0,arg0 + bv 0(r31) + EXTRS arg0,29,30,ret1 + +$$divI_8: + .EXPORT $$divI_8,MILLICODE + COMCLR,>= arg0,0,0 + ADDI 7,arg0,arg0 + bv 0(r31) + EXTRS arg0,28,29,ret1 + +$$divI_16: + .EXPORT $$divI_16,MILLICODE + COMCLR,>= arg0,0,0 + ADDI 15,arg0,arg0 + bv 0(r31) + EXTRS arg0,27,28,ret1 + +$$divI_3: + .EXPORT $$divI_3,MILLICODE + COMB,<,N arg0,0,$neg3 + + ADDI 1,arg0,arg0 + EXTRU arg0,1,2,ret1 + SH2ADD arg0,arg0,arg0 + B $pos + ADDC ret1,0,ret1 + +$neg3: + SUBI 1,arg0,arg0 + EXTRU arg0,1,2,ret1 + SH2ADD arg0,arg0,arg0 + B $neg + ADDC ret1,0,ret1 + +$$divU_3: + .EXPORT $$divU_3,MILLICODE + ADDI 1,arg0,arg0 + ADDC 0,0,ret1 + SHD ret1,arg0,30,t1 + SH2ADD arg0,arg0,arg0 + B $pos + ADDC ret1,t1,ret1 + +$$divI_5: + .EXPORT $$divI_5,MILLICODE + COMB,<,N arg0,0,$neg5 + ADDI 3,arg0,t1 + SH1ADD arg0,t1,arg0 + B $pos + ADDC 0,0,ret1 + +$neg5: + SUB 0,arg0,arg0 + ADDI 1,arg0,arg0 + SHD 0,arg0,31,ret1 + SH1ADD arg0,arg0,arg0 + B $neg + ADDC ret1,0,ret1 + +$$divU_5: + .EXPORT $$divU_5,MILLICODE + ADDI 1,arg0,arg0 + ADDC 0,0,ret1 + SHD ret1,arg0,31,t1 + SH1ADD arg0,arg0,arg0 + B $pos + ADDC t1,ret1,ret1 + +$$divI_6: + .EXPORT $$divI_6,MILLICODE + COMB,<,N arg0,0,$neg6 + EXTRU arg0,30,31,arg0 + ADDI 5,arg0,t1 + SH2ADD arg0,t1,arg0 + B $pos + ADDC 0,0,ret1 + +$neg6: + SUBI 2,arg0,arg0 + EXTRU arg0,30,31,arg0 + SHD 0,arg0,30,ret1 + SH2ADD arg0,arg0,arg0 + B $neg + ADDC ret1,0,ret1 + +$$divU_6: + .EXPORT $$divU_6,MILLICODE + EXTRU arg0,30,31,arg0 + ADDI 1,arg0,arg0 + SHD 0,arg0,30,ret1 + SH2ADD arg0,arg0,arg0 + B $pos + ADDC ret1,0,ret1 + +$$divU_10: + .EXPORT $$divU_10,MILLICODE + EXTRU arg0,30,31,arg0 + ADDI 3,arg0,t1 + SH1ADD arg0,t1,arg0 + ADDC 0,0,ret1 +$pos: + SHD ret1,arg0,28,t1 + SHD arg0,0,28,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 +$pos_for_17: + SHD ret1,arg0,24,t1 + SHD arg0,0,24,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 + + SHD ret1,arg0,16,t1 + SHD arg0,0,16,t2 + ADD arg0,t2,arg0 + bv 0(r31) + ADDC ret1,t1,ret1 + +$$divI_10: + .EXPORT $$divI_10,MILLICODE + COMB,< arg0,0,$neg10 + COPY 0,ret1 + EXTRU arg0,30,31,arg0 + ADDIB,TR 1,arg0,$pos + SH1ADD arg0,arg0,arg0 + +$neg10: + SUBI 2,arg0,arg0 + EXTRU arg0,30,31,arg0 + SH1ADD arg0,arg0,arg0 +$neg: + SHD ret1,arg0,28,t1 + SHD arg0,0,28,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 +$neg_for_17: + SHD ret1,arg0,24,t1 + SHD arg0,0,24,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 + + SHD ret1,arg0,16,t1 + SHD arg0,0,16,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 + bv 0(r31) + SUB 0,ret1,ret1 + +$$divI_12: + .EXPORT $$divI_12,MILLICODE + COMB,< arg0,0,$neg12 + COPY 0,ret1 + EXTRU arg0,29,30,arg0 + ADDIB,TR 1,arg0,$pos + SH2ADD arg0,arg0,arg0 + +$neg12: + SUBI 4,arg0,arg0 + EXTRU arg0,29,30,arg0 + B $neg + SH2ADD arg0,arg0,arg0 + +$$divU_12: + .EXPORT $$divU_12,MILLICODE + EXTRU arg0,29,30,arg0 + ADDI 5,arg0,t1 + SH2ADD arg0,t1,arg0 + B $pos + ADDC 0,0,ret1 + +$$divI_15: + .EXPORT $$divI_15,MILLICODE + COMB,< arg0,0,$neg15 + COPY 0,ret1 + ADDIB,TR 1,arg0,$pos+4 + SHD ret1,arg0,28,t1 + +$neg15: + B $neg + SUBI 1,arg0,arg0 + +$$divU_15: + .EXPORT $$divU_15,MILLICODE + ADDI 1,arg0,arg0 + B $pos + ADDC 0,0,ret1 + +$$divI_17: + .EXPORT $$divI_17,MILLICODE + COMB,<,N arg0,0,$neg17 + ADDI 1,arg0,arg0 + SHD 0,arg0,28,t1 + SHD arg0,0,28,t2 + SUB t2,arg0,arg0 + B $pos_for_17 + SUBB t1,0,ret1 + +$neg17: + SUBI 1,arg0,arg0 + SHD 0,arg0,28,t1 + SHD arg0,0,28,t2 + SUB t2,arg0,arg0 + B $neg_for_17 + SUBB t1,0,ret1 + +$$divU_17: + .EXPORT $$divU_17,MILLICODE + ADDI 1,arg0,arg0 + ADDC 0,0,ret1 + SHD ret1,arg0,28,t1 +$u17: + SHD arg0,0,28,t2 + SUB t2,arg0,arg0 + B $pos_for_17 + SUBB t1,ret1,ret1 + +$$divI_7: + .EXPORT $$divI_7,MILLICODE + COMB,<,N arg0,0,$neg7 +$7: + ADDI 1,arg0,arg0 + SHD 0,arg0,29,ret1 + SH3ADD arg0,arg0,arg0 + ADDC ret1,0,ret1 +$pos7: + SHD ret1,arg0,26,t1 + SHD arg0,0,26,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 + + SHD ret1,arg0,20,t1 + SHD arg0,0,20,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,t1 + + COPY 0,ret1 + SHD,= t1,arg0,24,t1 +$1: + ADDB,TR t1,ret1,$2 + EXTRU arg0,31,24,arg0 + + bv,n 0(r31) + +$2: + ADDB,TR t1,arg0,$1 + EXTRU,= arg0,7,8,t1 + +$neg7: + SUBI 1,arg0,arg0 +$8: + SHD 0,arg0,29,ret1 + SH3ADD arg0,arg0,arg0 + ADDC ret1,0,ret1 + +$neg7_shift: + SHD ret1,arg0,26,t1 + SHD arg0,0,26,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,ret1 + + SHD ret1,arg0,20,t1 + SHD arg0,0,20,t2 + ADD arg0,t2,arg0 + ADDC ret1,t1,t1 + + COPY 0,ret1 + SHD,= t1,arg0,24,t1 +$3: + ADDB,TR t1,ret1,$4 + EXTRU arg0,31,24,arg0 + + bv 0(r31) + SUB 0,ret1,ret1 + +$4: + ADDB,TR t1,arg0,$3 + EXTRU,= arg0,7,8,t1 + +$$divU_7: + .EXPORT $$divU_7,MILLICODE + ADDI 1,arg0,arg0 + ADDC 0,0,ret1 + SHD ret1,arg0,29,t1 + SH3ADD arg0,arg0,arg0 + B $pos7 + ADDC t1,ret1,ret1 + +$$divI_9: + .EXPORT $$divI_9,MILLICODE + COMB,<,N arg0,0,$neg9 + ADDI 1,arg0,arg0 + SHD 0,arg0,29,t1 + SHD arg0,0,29,t2 + SUB t2,arg0,arg0 + B $pos7 + SUBB t1,0,ret1 + +$neg9: + SUBI 1,arg0,arg0 + SHD 0,arg0,29,t1 + SHD arg0,0,29,t2 + SUB t2,arg0,arg0 + B $neg7_shift + SUBB t1,0,ret1 + +$$divU_9: + .EXPORT $$divU_9,MILLICODE + ADDI 1,arg0,arg0 + ADDC 0,0,ret1 + SHD ret1,arg0,29,t1 + SHD arg0,0,29,t2 + SUB t2,arg0,arg0 + B $pos7 + SUBB t1,ret1,ret1 + +$$divI_14: + .EXPORT $$divI_14,MILLICODE + COMB,<,N arg0,0,$neg14 +$$divU_14: + .EXPORT $$divU_14,MILLICODE + B $7 + EXTRU arg0,30,31,arg0 + +$neg14: + SUBI 2,arg0,arg0 + B $8 + EXTRU arg0,30,31,arg0 + + .PROCEND + .END + +rmndr: .EQU ret1 ; r29 + + .export $$remU,millicode +$$remU: + .proc + .callinfo NO_CALLS + .entry + + comib,>=,n 0,arg1,special_case + sub r0,arg1,rmndr ; clear carry, negate the divisor + ds r0,rmndr,r0 ; set V-bit to 1 + add arg0,arg0,temp ; shift msb bit into carry + ds r0,arg1,rmndr ; 1st divide step, if no carry + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 2nd divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 3rd divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 4th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 5th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 6th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 7th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 8th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 9th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 10th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 11th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 12th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 13th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 14th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 15th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 16th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 17th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 18th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 19th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 20th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 21st divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 22nd divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 23rd divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 24th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 25th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 26th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 27th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 28th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 29th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 30th divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 31st divide step + addc temp,temp,temp ; shift temp with/into carry + ds rmndr,arg1,rmndr ; 32nd divide step, + comiclr,<= 0,rmndr,r0 + add rmndr,arg1,rmndr ; correction +; .exit + bv,n 0(r31) + nop +; Putting >= on the last DS and deleting COMICLR does not work! +;_____________________________________________________________________________ +special_case: + addit,= 0,arg1,r0 ; trap on div by zero + sub,>>= arg0,arg1,rmndr + copy arg0,rmndr + .exit + bv,n 0(r31) + nop + .procend + .end + +; Use bv 0(r31) and bv,n 0(r31) instead. +; #define return bv 0(%mrp) +; #define return_n bv,n 0(%mrp) + + .align 16 +$$mulI: + + .proc + .callinfo NO_CALLS + .export $$mulI, millicode + combt,<<= %r25,%r26,l4 ; swap args if unsigned %r25>%r26 + copy 0,%r29 ; zero out the result + xor %r26,%r25,%r26 ; swap %r26 & %r25 using the + xor %r26,%r25,%r25 ; old xor trick + xor %r26,%r25,%r26 +l4: combt,<= 0,%r26,l3 ; if %r26>=0 then proceed like unsigned + + zdep %r25,30,8,%r1 ; %r1 = (%r25&0xff)<<1 ********* + sub,> 0,%r25,%r1 ; otherwise negate both and + combt,<=,n %r26,%r1,l2 ; swap back if |%r26|<|%r25| + sub 0,%r26,%r25 + movb,tr,n %r1,%r26,l2 ; 10th inst. + +l0: add %r29,%r1,%r29 ; add in this partial product + +l1: zdep %r26,23,24,%r26 ; %r26 <<= 8 ****************** + +l2: zdep %r25,30,8,%r1 ; %r1 = (%r25&0xff)<<1 ********* + +l3: blr %r1,0 ; case on these 8 bits ****** + + extru %r25,23,24,%r25 ; %r25 >>= 8 ****************** + +;16 insts before this. +; %r26 <<= 8 ************************** +x0: comb,<> %r25,0,l2 ! zdep %r26,23,24,%r26 ! bv,n 0(r31) ! nop + +x1: comb,<> %r25,0,l1 ! add %r29,%r26,%r29 ! bv,n 0(r31) ! nop + +x2: comb,<> %r25,0,l1 ! sh1add %r26,%r29,%r29 ! bv,n 0(r31) ! nop + +x3: comb,<> %r25,0,l0 ! sh1add %r26,%r26,%r1 ! bv 0(r31) ! add %r29,%r1,%r29 + +x4: comb,<> %r25,0,l1 ! sh2add %r26,%r29,%r29 ! bv,n 0(r31) ! nop + +x5: comb,<> %r25,0,l0 ! sh2add %r26,%r26,%r1 ! bv 0(r31) ! add %r29,%r1,%r29 + +x6: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh1add %r1,%r29,%r29 ! bv,n 0(r31) + +x7: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh2add %r26,%r29,%r29 ! b,n ret_t0 + +x8: comb,<> %r25,0,l1 ! sh3add %r26,%r29,%r29 ! bv,n 0(r31) ! nop + +x9: comb,<> %r25,0,l0 ! sh3add %r26,%r26,%r1 ! bv 0(r31) ! add %r29,%r1,%r29 + +x10: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh1add %r1,%r29,%r29 ! bv,n 0(r31) + +x11: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh3add %r26,%r29,%r29 ! b,n ret_t0 + +x12: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh2add %r1,%r29,%r29 ! bv,n 0(r31) + +x13: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh3add %r26,%r29,%r29 ! b,n ret_t0 + +x14: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x15: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh1add %r1,%r1,%r1 ! b,n ret_t0 + +x16: zdep %r26,27,28,%r1 ! comb,<> %r25,0,l1 ! add %r29,%r1,%r29 ! bv,n 0(r31) + +x17: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh3add %r26,%r1,%r1 ! b,n ret_t0 + +x18: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh1add %r1,%r29,%r29 ! bv,n 0(r31) + +x19: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh1add %r1,%r26,%r1 ! b,n ret_t0 + +x20: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh2add %r1,%r29,%r29 ! bv,n 0(r31) + +x21: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh2add %r1,%r26,%r1 ! b,n ret_t0 + +x22: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x23: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x24: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh3add %r1,%r29,%r29 ! bv,n 0(r31) + +x25: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh2add %r1,%r1,%r1 ! b,n ret_t0 + +x26: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x27: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh3add %r1,%r1,%r1 ! b,n ret_t0 + +x28: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x29: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x30: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x31: zdep %r26,26,27,%r1 ! comb,<> %r25,0,l0 ! sub %r1,%r26,%r1 ! b,n ret_t0 + +x32: zdep %r26,26,27,%r1 ! comb,<> %r25,0,l1 ! add %r29,%r1,%r29 ! bv,n 0(r31) + +x33: sh3add %r26,0,%r1 ! comb,<> %r25,0,l0 ! sh2add %r1,%r26,%r1 ! b,n ret_t0 + +x34: zdep %r26,27,28,%r1 ! add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x35: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh3add %r26,%r1,%r1 + +x36: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh2add %r1,%r29,%r29 ! bv,n 0(r31) + +x37: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh2add %r1,%r26,%r1 ! b,n ret_t0 + +x38: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x39: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x40: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh3add %r1,%r29,%r29 ! bv,n 0(r31) + +x41: sh2add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh3add %r1,%r26,%r1 ! b,n ret_t0 + +x42: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x43: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x44: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x45: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! sh2add %r1,%r1,%r1 ! b,n ret_t0 + +x46: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! add %r1,%r26,%r1 + +x47: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh1add %r26,%r1,%r1 + +x48: sh1add %r26,%r26,%r1 ! comb,<> %r25,0,l0 ! zdep %r1,27,28,%r1 ! b,n ret_t0 + +x49: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r26,%r1,%r1 + +x50: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x51: sh3add %r26,%r26,%r1 ! sh3add %r26,%r1,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x52: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x53: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x54: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x55: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x56: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x57: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x58: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x59: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t02a0 ! sh1add %r1,%r1,%r1 + +x60: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x61: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x62: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x63: zdep %r26,25,26,%r1 ! comb,<> %r25,0,l0 ! sub %r1,%r26,%r1 ! b,n ret_t0 + +x64: zdep %r26,25,26,%r1 ! comb,<> %r25,0,l1 ! add %r29,%r1,%r29 ! bv,n 0(r31) + +x65: sh3add %r26,0,%r1 ! comb,<> %r25,0,l0 ! sh3add %r1,%r26,%r1 ! b,n ret_t0 + +x66: zdep %r26,26,27,%r1 ! add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x67: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x68: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x69: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x70: zdep %r26,25,26,%r1 ! sh2add %r26,%r1,%r1 ! b e_t0 ! sh1add %r26,%r1,%r1 + +x71: sh3add %r26,%r26,%r1 ! sh3add %r1,0,%r1 ! b e_t0 ! sub %r1,%r26,%r1 + +x72: sh3add %r26,%r26,%r1 ! comb,<> %r25,0,l1 ! sh3add %r1,%r29,%r29 ! bv,n 0(r31) + +x73: sh3add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_shift ! add %r29,%r1,%r29 + +x74: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x75: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x76: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x77: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x78: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x79: zdep %r26,27,28,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sub %r1,%r26,%r1 + +x80: zdep %r26,27,28,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! add %r29,%r1,%r29 + +x81: sh3add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_shift ! add %r29,%r1,%r29 + +x82: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x83: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x84: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x85: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x86: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x87: sh3add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_t02a0 ! sh2add %r26,%r1,%r1 + +x88: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x89: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x90: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x91: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x92: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh1add %r1,%r26,%r1 + +x93: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x94: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0 ! sh1add %r26,%r1,%r1 + +x95: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x96: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x97: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x98: zdep %r26,26,27,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh1add %r26,%r1,%r1 + +x99: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x100: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x101: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x102: zdep %r26,26,27,%r1 ! sh1add %r26,%r1,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x103: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t02a0 ! sh2add %r1,%r26,%r1 + +x104: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x105: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x106: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x107: sh3add %r26,%r26,%r1 ! sh2add %r26,%r1,%r1 ! b e_t02a0 ! sh3add %r1,%r26,%r1 + +x108: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x109: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x110: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x111: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x112: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! zdep %r1,27,28,%r1 + +x113: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t02a0 ! sh1add %r1,%r1,%r1 + +x114: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r1,%r1 + +x115: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r1,%r1 + +x116: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh2add %r1,%r26,%r1 + +x117: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r1,%r1 + +x118: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0a0 ! sh3add %r1,%r1,%r1 + +x119: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t02a0 ! sh3add %r1,%r1,%r1 + +x120: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x121: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x122: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x123: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x124: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x125: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x126: zdep %r26,25,26,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x127: zdep %r26,24,25,%r1 ! comb,<> %r25,0,l0 ! sub %r1,%r26,%r1 ! b,n ret_t0 + +x128: zdep %r26,24,25,%r1 ! comb,<> %r25,0,l1 ! add %r29,%r1,%r29 ! bv,n 0(r31) + +x129: zdep %r26,24,25,%r1 ! comb,<> %r25,0,l0 ! add %r1,%r26,%r1 ! b,n ret_t0 + +x130: zdep %r26,25,26,%r1 ! add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x131: sh3add %r26,0,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x132: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x133: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x134: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x135: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x136: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x137: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x138: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x139: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0a0 ! sh2add %r1,%r26,%r1 + +x140: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh2add %r1,%r1,%r1 + +x141: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0a0 ! sh1add %r1,%r26,%r1 + +x142: sh3add %r26,%r26,%r1 ! sh3add %r1,0,%r1 ! b e_2t0 ! sub %r1,%r26,%r1 + +x143: zdep %r26,27,28,%r1 ! sh3add %r1,%r1,%r1 ! b e_t0 ! sub %r1,%r26,%r1 + +x144: sh3add %r26,%r26,%r1 ! sh3add %r1,0,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x145: sh3add %r26,%r26,%r1 ! sh3add %r1,0,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x146: sh3add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x147: sh3add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x148: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x149: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x150: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x151: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r26,%r1 + +x152: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x153: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x154: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x155: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x156: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh1add %r1,%r26,%r1 + +x157: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_t02a0 ! sh2add %r1,%r1,%r1 + +x158: zdep %r26,27,28,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0 ! sub %r1,%r26,%r1 + +x159: zdep %r26,26,27,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sub %r1,%r26,%r1 + +x160: sh2add %r26,%r26,%r1 ! sh2add %r1,0,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x161: sh3add %r26,0,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x162: sh3add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x163: sh3add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_t0 ! sh1add %r1,%r26,%r1 + +x164: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x165: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x166: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x167: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r26,%r1 + +x168: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x169: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x170: zdep %r26,26,27,%r1 ! sh1add %r26,%r1,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x171: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r1,%r1 + +x172: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_4t0 ! sh1add %r1,%r26,%r1 + +x173: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t02a0 ! sh3add %r1,%r1,%r1 + +x174: zdep %r26,26,27,%r1 ! sh1add %r26,%r1,%r1 ! b e_t04a0 ! sh2add %r1,%r1,%r1 + +x175: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_5t0 ! sh1add %r1,%r26,%r1 + +x176: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_8t0 ! add %r1,%r26,%r1 + +x177: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_8t0a0 ! add %r1,%r26,%r1 + +x178: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh3add %r1,%r26,%r1 + +x179: sh2add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0a0 ! sh3add %r1,%r26,%r1 + +x180: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x181: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x182: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0 ! sh1add %r1,%r26,%r1 + +x183: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0a0 ! sh1add %r1,%r26,%r1 + +x184: sh2add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_4t0 ! add %r1,%r26,%r1 + +x185: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x186: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r1,%r1 + +x187: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t02a0 ! sh2add %r1,%r1,%r1 + +x188: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_4t0 ! sh1add %r26,%r1,%r1 + +x189: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r1,%r1 + +x190: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r1,%r1 + +x191: zdep %r26,25,26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sub %r1,%r26,%r1 + +x192: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x193: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x194: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x195: sh3add %r26,0,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x196: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_4t0 ! sh1add %r1,%r26,%r1 + +x197: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_4t0a0 ! sh1add %r1,%r26,%r1 + +x198: zdep %r26,25,26,%r1 ! sh1add %r26,%r1,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x199: sh3add %r26,0,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r1,%r1 + +x200: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x201: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x202: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x203: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0a0 ! sh2add %r1,%r26,%r1 + +x204: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh1add %r1,%r1,%r1 + +x205: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x206: zdep %r26,25,26,%r1 ! sh2add %r26,%r1,%r1 ! b e_t02a0 ! sh1add %r1,%r1,%r1 + +x207: sh3add %r26,0,%r1 ! sh1add %r1,%r26,%r1 ! b e_3t0 ! sh2add %r1,%r26,%r1 + +x208: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_8t0 ! add %r1,%r26,%r1 + +x209: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_8t0a0 ! add %r1,%r26,%r1 + +x210: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh2add %r1,%r1,%r1 + +x211: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0a0 ! sh2add %r1,%r1,%r1 + +x212: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_4t0 ! sh2add %r1,%r26,%r1 + +x213: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_4t0a0 ! sh2add %r1,%r26,%r1 + +x214: sh3add %r26,%r26,%r1 ! sh2add %r26,%r1,%r1 ! b e2t04a0 ! sh3add %r1,%r26,%r1 + +x215: sh2add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_5t0 ! sh1add %r1,%r26,%r1 + +x216: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x217: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x218: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_2t0 ! sh2add %r1,%r26,%r1 + +x219: sh3add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x220: sh1add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_4t0 ! sh1add %r1,%r26,%r1 + +x221: sh1add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_4t0a0 ! sh1add %r1,%r26,%r1 + +x222: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r1,%r1 + +x223: sh3add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r1,%r1 + +x224: sh3add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_8t0 ! add %r1,%r26,%r1 + +x225: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0 ! sh2add %r1,%r1,%r1 + +x226: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_t02a0 ! zdep %r1,26,27,%r1 + +x227: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_t02a0 ! sh2add %r1,%r1,%r1 + +x228: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0 ! sh1add %r1,%r1,%r1 + +x229: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_4t0a0 ! sh1add %r1,%r1,%r1 + +x230: sh3add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_5t0 ! add %r1,%r26,%r1 + +x231: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_3t0 ! sh2add %r1,%r26,%r1 + +x232: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_8t0 ! sh2add %r1,%r26,%r1 + +x233: sh1add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e_8t0a0 ! sh2add %r1,%r26,%r1 + +x234: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0 ! sh3add %r1,%r1,%r1 + +x235: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e_2t0a0 ! sh3add %r1,%r1,%r1 + +x236: sh3add %r26,%r26,%r1 ! sh1add %r1,%r26,%r1 ! b e4t08a0 ! sh1add %r1,%r1,%r1 + +x237: zdep %r26,27,28,%r1 ! sh2add %r1,%r1,%r1 ! b e_3t0 ! sub %r1,%r26,%r1 + +x238: sh1add %r26,%r26,%r1 ! sh2add %r1,%r26,%r1 ! b e2t04a0 ! sh3add %r1,%r1,%r1 + +x239: zdep %r26,27,28,%r1 ! sh2add %r1,%r1,%r1 ! b e_t0ma0 ! sh1add %r1,%r1,%r1 + +x240: sh3add %r26,%r26,%r1 ! add %r1,%r26,%r1 ! b e_8t0 ! sh1add %r1,%r1,%r1 + +x241: sh3add %r26,%r26,%r1 ! add %r1,%r26,%r1 ! b e_8t0a0 ! sh1add %r1,%r1,%r1 + +x242: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_2t0 ! sh3add %r1,%r26,%r1 + +x243: sh3add %r26,%r26,%r1 ! sh3add %r1,%r1,%r1 ! b e_t0 ! sh1add %r1,%r1,%r1 + +x244: sh2add %r26,%r26,%r1 ! sh1add %r1,%r1,%r1 ! b e_4t0 ! sh2add %r1,%r26,%r1 + +x245: sh3add %r26,0,%r1 ! sh1add %r1,%r1,%r1 ! b e_5t0 ! sh1add %r1,%r26,%r1 + +x246: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_2t0 ! sh1add %r1,%r1,%r1 + +x247: sh2add %r26,%r26,%r1 ! sh3add %r1,%r26,%r1 ! b e_2t0a0 ! sh1add %r1,%r1,%r1 + +x248: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh3add %r1,%r29,%r29 + +x249: zdep %r26,26,27,%r1 ! sub %r1,%r26,%r1 ! b e_t0 ! sh3add %r1,%r26,%r1 + +x250: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0 ! sh2add %r1,%r1,%r1 + +x251: sh2add %r26,%r26,%r1 ! sh2add %r1,%r1,%r1 ! b e_2t0a0 ! sh2add %r1,%r1,%r1 + +x252: zdep %r26,25,26,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh2add %r1,%r29,%r29 + +x253: zdep %r26,25,26,%r1 ! sub %r1,%r26,%r1 ! b e_t0 ! sh2add %r1,%r26,%r1 + +x254: zdep %r26,24,25,%r1 ! sub %r1,%r26,%r1 ! b e_shift ! sh1add %r1,%r29,%r29 + +x255: zdep %r26,23,24,%r1 ! comb,<> %r25,0,l0 ! sub %r1,%r26,%r1 ! b,n ret_t0 + +;1040 insts before this. +ret_t0: bv 0(r31) + +e_t0: add %r29,%r1,%r29 + +e_shift: comb,<> %r25,0,l2 + + zdep %r26,23,24,%r26 ; %r26 <<= 8 *********** + bv,n 0(r31) +e_t0ma0: comb,<> %r25,0,l0 + + sub %r1,%r26,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_t0a0: comb,<> %r25,0,l0 + + add %r1,%r26,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_t02a0: comb,<> %r25,0,l0 + + sh1add %r26,%r1,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_t04a0: comb,<> %r25,0,l0 + + sh2add %r26,%r1,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_2t0: comb,<> %r25,0,l1 + + sh1add %r1,%r29,%r29 + bv,n 0(r31) +e_2t0a0: comb,<> %r25,0,l0 + + sh1add %r1,%r26,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e2t04a0: sh1add %r26,%r1,%r1 + + comb,<> %r25,0,l1 + sh1add %r1,%r29,%r29 + bv,n 0(r31) +e_3t0: comb,<> %r25,0,l0 + + sh1add %r1,%r1,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_4t0: comb,<> %r25,0,l1 + + sh2add %r1,%r29,%r29 + bv,n 0(r31) +e_4t0a0: comb,<> %r25,0,l0 + + sh2add %r1,%r26,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e4t08a0: sh1add %r26,%r1,%r1 + + comb,<> %r25,0,l1 + sh2add %r1,%r29,%r29 + bv,n 0(r31) +e_5t0: comb,<> %r25,0,l0 + + sh2add %r1,%r1,%r1 + bv 0(r31) + add %r29,%r1,%r29 +e_8t0: comb,<> %r25,0,l1 + + sh3add %r1,%r29,%r29 + bv,n 0(r31) +e_8t0a0: comb,<> %r25,0,l0 + + sh3add %r1,%r26,%r1 + bv 0(r31) + add %r29,%r1,%r29 + + .procend + .end + + .import $$divI_2,millicode + .import $$divI_3,millicode + .import $$divI_4,millicode + .import $$divI_5,millicode + .import $$divI_6,millicode + .import $$divI_7,millicode + .import $$divI_8,millicode + .import $$divI_9,millicode + .import $$divI_10,millicode + .import $$divI_12,millicode + .import $$divI_14,millicode + .import $$divI_15,millicode + .export $$divI,millicode + .export $$divoI,millicode +$$divoI: + .proc + .callinfo NO_CALLS + comib,=,n -1,arg1,negative1 ; when divisor == -1 +$$divI: + comib,>>=,n 15,arg1,small_divisor + add,>= 0,arg0,retreg ; move dividend, if retreg < 0, +normal1: + sub 0,retreg,retreg ; make it positive + sub 0,arg1,temp ; clear carry, + ; negate the divisor + ds 0,temp,0 ; set V-bit to the comple- + ; ment of the divisor sign + add retreg,retreg,retreg ; shift msb bit into carry + ds r0,arg1,temp ; 1st divide step, if no carry + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 2nd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 3rd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 4th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 5th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 6th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 7th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 8th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 9th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 10th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 11th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 12th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 13th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 14th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 15th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 16th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 17th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 18th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 19th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 20th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 21st divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 22nd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 23rd divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 24th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 25th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 26th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 27th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 28th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 29th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 30th divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 31st divide step + addc retreg,retreg,retreg ; shift retreg with/into carry + ds temp,arg1,temp ; 32nd divide step, + addc retreg,retreg,retreg ; shift last retreg bit into retreg + xor,>= arg0,arg1,0 ; get correct sign of quotient + sub 0,retreg,retreg ; based on operand signs + bv,n 0(r31) + nop +;______________________________________________________________________ +small_divisor: + blr,n arg1,r0 + nop +; table for divisor == 0,1, ... ,15 + addit,= 0,arg1,r0 ; trap if divisor == 0 + nop + bv 0(r31) ; divisor == 1 + copy arg0,retreg + b,n $$divI_2 ; divisor == 2 + nop + b,n $$divI_3 ; divisor == 3 + nop + b,n $$divI_4 ; divisor == 4 + nop + b,n $$divI_5 ; divisor == 5 + nop + b,n $$divI_6 ; divisor == 6 + nop + b,n $$divI_7 ; divisor == 7 + nop + b,n $$divI_8 ; divisor == 8 + nop + b,n $$divI_9 ; divisor == 9 + nop + b,n $$divI_10 ; divisor == 10 + nop + b normal1 ; divisor == 11 + add,>= 0,arg0,retreg + b,n $$divI_12 ; divisor == 12 + nop + b normal1 ; divisor == 13 + add,>= 0,arg0,retreg + b,n $$divI_14 ; divisor == 14 + nop + b,n $$divI_15 ; divisor == 15 + nop +;______________________________________________________________________ +negative1: + sub 0,arg0,retreg ; result is negation of dividend + bv 0(r31) + addo arg0,arg1,r0 ; trap iff dividend==0x80000000 && divisor==-1 + .procend + .end diff --git a/sys/lib/libkern/arch/hppa/prefix.h b/sys/lib/libkern/arch/hppa/prefix.h new file mode 100644 index 000000000..1c49a8730 --- /dev/null +++ b/sys/lib/libkern/arch/hppa/prefix.h @@ -0,0 +1,85 @@ +/* $NetBSD: prefix.h,v 1.1 2002/06/06 20:03:39 fredette Exp $ */ + +/* $OpenBSD: prefix.h,v 1.2 2001/03/29 04:08:21 mickey Exp $ */ + +/* + * (c) Copyright 1985 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ + +/* + * STANDARD INCLUDE FILE FOR MILLICODE + * Every source file must include this file. + * + * Hardware General Registers + * + * Frame Offsets (millicode convention!) + * Used when calling other millicode routines. + * Stack unwinding is dependent upon these definitions. + * r31_slot .equ -20 + * sr0_slot .equ -16 + */ + +#include + +#define DEFINE(name, value)name: .EQU value +#ifdef milliext +#ifdef PIC +#define MILLI_BE(lbl) \ + BL .+8,r1\ + ! ADDIL L%lbl-labl/**/lbl,r1\ + ! .LABEL labl/**/lbl\ + ! BE R%lbl-labl/**/lbl(sr7,r1) + +#define MILLI_BEN(lbl) \ + BL .+8,r1\ + ! ADDIL L%lbl-labl/**/lbl,r1\ + ! .LABEL labl/**/lbl\ + ! BE,N R%lbl-labl/**/lbl(sr7,r1) + +#define MILLI_BLE(lbl) \ + BL .+8,r1\ + ! ADDIL L%lbl-labl/**/lbl,r1\ + ! .LABEL labl/**/lbl \ + ! BLE R%lbl-labl/**/lbl(sr7,r1) + +#define MILLI_BLEN(lbl) \ + BL .+8,r1\ + ! ADDIL L%lbl-labl/**/lbl,r1\ + ! .LABEL labl/**/lbl\ + ! BLE,N R%lbl-labl/**/lbl(sr7,r1) +#else +#define MILLI_BE(lbl) BE lbl(sr7,r0) +#define MILLI_BEN(lbl) BE,n lbl(sr7,r0) +#define MILLI_BLE(lbl) BLE lbl(sr7,r0) +#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0) +#endif + +#define MILLIRETN BE,n 0(sr0,r31) +#define MILLIRET BE 0(sr0,r31) +#define MILLI_RETN BE,n 0(sr0,r31) +#define MILLI_RET BE 0(sr0,r31) + +#else +#define MILLI_BE(lbl) B lbl +#define MILLI_BEN(lbl) B,n lbl +#define MILLI_BLE(lbl) BL lbl,r31 +#define MILLI_BLEN(lbl) BL,n lbl,r31 +#define MILLIRETN BV,n 0(r31) +#define MILLIRET BV 0(r31) +#define MILLI_RETN BV,n 0(r31) +#define MILLI_RET BV 0(r31) +#endif +; VERSION is used wherever ".version" can appear in a routine +;#define VERSION .version +#define VERSION ; diff --git a/sys/lib/libkern/arch/hppa/spcopy.S b/sys/lib/libkern/arch/hppa/spcopy.S new file mode 100644 index 000000000..da462b9ea --- /dev/null +++ b/sys/lib/libkern/arch/hppa/spcopy.S @@ -0,0 +1,4 @@ +/* $NetBSD: spcopy.S,v 1.1 2002/06/06 20:03:39 fredette Exp $ */ + +#define SPCOPY +#include "bcopy.S" diff --git a/sys/lib/libkern/arch/i386/Makefile.inc b/sys/lib/libkern/arch/i386/Makefile.inc new file mode 100644 index 000000000..e0c45969c --- /dev/null +++ b/sys/lib/libkern/arch/i386/Makefile.inc @@ -0,0 +1,11 @@ +# $NetBSD: Makefile.inc,v 1.31 2009/08/14 19:23:53 dsl Exp $ + +SRCS+= byte_swap_2.S byte_swap_4.S ffs.S +SRCS+= memchr.S memcmp.S memcpy.S memmove.S memset.S +SRCS+= random.S +SRCS+= strcat.S strchr.S strcmp.S +SRCS+= strcpy.S strlen.S +SRCS+= strrchr.S +SRCS+= scanc.S skpc.S + +SRCS+= crc32.c diff --git a/sys/lib/libkern/arch/i386/random.S b/sys/lib/libkern/arch/i386/random.S new file mode 100644 index 000000000..9670ff1aa --- /dev/null +++ b/sys/lib/libkern/arch/i386/random.S @@ -0,0 +1,96 @@ +/* $NetBSD: random.S,v 1.6 2010/09/07 20:35:50 pooka Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ +#include + + .data +randseed: + .long 1 + .text +ENTRY(random) + movl $16807,%eax + PIC_PROLOGUE + imull PIC_GOTOFF(randseed) + PIC_EPILOGUE + shld $1,%eax,%edx + andl $0x7fffffff,%eax + addl %edx,%eax + js neg + PIC_PROLOGUE + movl %eax,PIC_GOTOFF(randseed) + PIC_EPILOGUE + ret +neg: + subl $0x7fffffff,%eax + PIC_PROLOGUE + movl %eax,PIC_GOTOFF(randseed) + PIC_EPILOGUE + ret diff --git a/sys/lib/libkern/arch/i386/scanc.S b/sys/lib/libkern/arch/i386/scanc.S new file mode 100644 index 000000000..6f77e83b7 --- /dev/null +++ b/sys/lib/libkern/arch/i386/scanc.S @@ -0,0 +1,56 @@ +/* $NetBSD: scanc.S,v 1.9 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +ENTRY(scanc) + movl 4(%esp),%ecx + testl %ecx,%ecx + jz 3f + pushl %esi + pushl %edi + movl 16(%esp),%esi + movl 20(%esp),%edi + movb 24(%esp),%dl + xorl %eax,%eax + cld +1: + lodsb + testb %dl,(%eax,%edi) + jnz 2f + decl %ecx + jnz 1b +2: + popl %edi + popl %esi +3: + movl %ecx,%eax + ret diff --git a/sys/lib/libkern/arch/i386/skpc.S b/sys/lib/libkern/arch/i386/skpc.S new file mode 100644 index 000000000..fddb7b36e --- /dev/null +++ b/sys/lib/libkern/arch/i386/skpc.S @@ -0,0 +1,47 @@ +/* $NetBSD: skpc.S,v 1.6 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +ENTRY(skpc) + pushl %edi + movl 16(%esp),%edi + movl 12(%esp),%ecx + movl 8(%esp),%eax + cld + repe + scasb + je 1f + incl %ecx +1: + movl %ecx,%eax + popl %edi + ret diff --git a/sys/lib/libkern/arch/ia64/Makefile.inc b/sys/lib/libkern/arch/ia64/Makefile.inc new file mode 100644 index 000000000..c55b01e08 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/Makefile.inc @@ -0,0 +1,8 @@ +# $NetBSD: Makefile.inc,v 1.4 2009/08/14 19:23:54 dsl Exp $ +# + +SRCS+= ffs.c + +SRCS+= divdi3.S divsi3.S modsi3.S moddi3.S udivdi3.S udivsi3.S +SRCS+= umoddi3.S umodsi3.S bswap64.S bswap32.S bswap16.S ntohl.S htonl.S +SRCS+= memcpy.S diff --git a/sys/lib/libkern/arch/ia64/bswap16.S b/sys/lib/libkern/arch/ia64/bswap16.S new file mode 100644 index 000000000..95f0dfef8 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/bswap16.S @@ -0,0 +1,37 @@ +/* $NetBSD: bswap16.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * from: NetBSD: htons.S,v 1.1 1996/04/17 22:36:54 cgd + * from: src/sys/libkern/ia64/htons.S,v 1.2 2002/02/18 20:35:21 + * + * $FreeBSD$ + */ + +#define NAME bswap16 + +#include "byte_swap_2.S" diff --git a/sys/lib/libkern/arch/ia64/bswap32.S b/sys/lib/libkern/arch/ia64/bswap32.S new file mode 100644 index 000000000..7cf66de9e --- /dev/null +++ b/sys/lib/libkern/arch/ia64/bswap32.S @@ -0,0 +1,37 @@ +/* $NetBSD: bswap32.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * from: NetBSD: htonl.S,v 1.1 1996/04/17 22:36:52 cgd + * from: src/sys/libkern/ia64/htonl.S,v 1.2 2002/02/18 20:35:21 + * + * $FreeBSD$ + */ + +#define NAME bswap32 + +#include "byte_swap_4.S" diff --git a/sys/lib/libkern/arch/ia64/bswap64.S b/sys/lib/libkern/arch/ia64/bswap64.S new file mode 100644 index 000000000..1214379e5 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/bswap64.S @@ -0,0 +1,37 @@ +/* $NetBSD: bswap64.S,v 1.1 2009/07/20 11:23:04 kiyohara Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * from: NetBSD: htonl.S,v 1.1 1996/04/17 22:36:52 cgd + * from: src/sys/libkern/ia64/htonl.S,v 1.2 2002/02/18 20:35:21 + * + * $FreeBSD$ + */ + +#define NAME bswap64 + +#include "byte_swap_8.S" diff --git a/sys/lib/libkern/arch/ia64/byte_swap_2.S b/sys/lib/libkern/arch/ia64/byte_swap_2.S new file mode 100644 index 000000000..975bc9c7a --- /dev/null +++ b/sys/lib/libkern/arch/ia64/byte_swap_2.S @@ -0,0 +1,46 @@ +/* $NetBSD: byte_swap_2.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include + +#ifndef NAME +#error NAME not defined +#endif + +/* + * Byte-swap a 2-byte quantity. (Convert 0x0123 to 0x2301.) + * + * Argument is an unsigned 2-byte integer (u_int16_t). + */ +ENTRY(NAME, 1) + mux1 r16=in0,@rev + ;; + extr.u r8=r16,48,16 + br.ret.sptk.few rp +END(NAME) diff --git a/sys/lib/libkern/arch/ia64/byte_swap_4.S b/sys/lib/libkern/arch/ia64/byte_swap_4.S new file mode 100644 index 000000000..a600aa4fb --- /dev/null +++ b/sys/lib/libkern/arch/ia64/byte_swap_4.S @@ -0,0 +1,46 @@ +/* $NetBSD: byte_swap_4.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include + +#ifndef NAME +#error NAME not defined +#endif + +/* + * Byte-swap a 4-byte quantity. (Convert 0x01234567 to 0x67452301.) + * + * Argument is an unsigned 4-byte integer (u_int32_t). + */ +ENTRY(NAME, 1) + mux1 r16=in0,@rev + ;; + extr.u r8=r16,32,32 + br.ret.sptk.few rp +END(NAME) diff --git a/sys/lib/libkern/arch/ia64/byte_swap_8.S b/sys/lib/libkern/arch/ia64/byte_swap_8.S new file mode 100644 index 000000000..aee67843e --- /dev/null +++ b/sys/lib/libkern/arch/ia64/byte_swap_8.S @@ -0,0 +1,45 @@ +/* $NetBSD: byte_swap_8.S,v 1.1 2009/07/20 11:23:04 kiyohara Exp $ */ + +/*- + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include + +#ifndef NAME +#error NAME not defined +#endif + +/* + * Byte-swap a 8-byte quantity. + * (Convert 0x0123456789012345 to 0x4523018967452301.) + * + * Argument is an unsigned 8-byte integer (u_int64_t). + */ +ENTRY(NAME, 1) + mux1 r8=in0,@rev + br.ret.sptk.few rp +END(NAME) diff --git a/sys/lib/libkern/arch/ia64/divdi3.S b/sys/lib/libkern/arch/ia64/divdi3.S new file mode 100644 index 000000000..9c518283e --- /dev/null +++ b/sys/lib/libkern/arch/ia64/divdi3.S @@ -0,0 +1,142 @@ +.file "__divdi3.s" + +// $NetBSD: divdi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text +.proc __divdi3# +.align 32 +.global __divdi3# +.align 32 + +// 64-bit signed integer divide + +__divdi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mmi + + // 64-BIT SIGNED INTEGER DIVIDE BEGINS HERE + + setf.sig f8=r32 + setf.sig f9=r33 + nop.i 0;; +} { .mfb + nop.m 0 + fcvt.xf f6=f8 + nop.b 0 +} { .mfb + nop.m 0 + fcvt.xf f7=f9 + nop.b 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfb + nop.m 0 + // Step (11) + // q = trunc (q3) + fcvt.fx.trunc.s1 f8=f8 + nop.b 0;; +} { .mmi + // quotient will be in r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 64-BIT SIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __divdi3 diff --git a/sys/lib/libkern/arch/ia64/divsi3.S b/sys/lib/libkern/arch/ia64/divsi3.S new file mode 100644 index 000000000..7cb55d01d --- /dev/null +++ b/sys/lib/libkern/arch/ia64/divsi3.S @@ -0,0 +1,124 @@ +.file "__divsi3.s" + +// $NetBSD: divsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + +// 32-bit signed integer divide + +.proc __divsi3# +.align 32 +.global __divsi3# +.align 32 + +__divsi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mii + nop.m 0 + + // 32-BIT SIGNED INTEGER DIVIDE BEGINS HERE + + // general register used: + // r32 - 32-bit signed integer dividend + // r33 - 32-bit signed integer divisor + // r8 - 32-bit signed integer result + // r2 - scratch register + // floating-point registers used: f6, f7, f8, f9 + // predicate registers used: p6 + + sxt4 r32=r32 + sxt4 r33=r33;; +} { .mmb + setf.sig f6=r32 + setf.sig f7=r33 + nop.b 0;; +} { .mfi + nop.m 0 + fcvt.xf f6=f6 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xf f7=f7 + mov r2 = 0x0ffdd;; +} { .mfi + setf.exp f9 = r2 + // (1) y0 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // (2) q0 = a * y0 + (p6) fma.s1 f6=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // (3) e0 = 1 - b * y0 + (p6) fnma.s1 f7=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // (4) q1 = q0 + e0 * q0 + (p6) fma.s1 f6=f7,f6,f6 + nop.i 0 +} { .mfi + nop.m 0 + // (5) e1 = e0 * e0 + 2^-34 + (p6) fma.s1 f7=f7,f7,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (6) q2 = q1 + e1 * q1 + (p6) fma.s1 f8=f7,f6,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // (7) q = trunc(q2) + fcvt.fx.trunc.s1 f8=f8 + nop.i 0;; +} { .mmi + // quotient will be in the least significant 32 bits of r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 32-BIT SIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __divsi3 diff --git a/sys/lib/libkern/arch/ia64/htonl.S b/sys/lib/libkern/arch/ia64/htonl.S new file mode 100644 index 000000000..3bae41fc1 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/htonl.S @@ -0,0 +1,32 @@ +/* $NetBSD: htonl.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME htonl + +#include "byte_swap_4.S" diff --git a/sys/lib/libkern/arch/ia64/memcpy.S b/sys/lib/libkern/arch/ia64/memcpy.S new file mode 100644 index 000000000..67c83ce41 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/memcpy.S @@ -0,0 +1,4 @@ +/* $NetBSD: memcpy.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */ + +#include + diff --git a/sys/lib/libkern/arch/ia64/moddi3.S b/sys/lib/libkern/arch/ia64/moddi3.S new file mode 100644 index 000000000..32ad0a2d8 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/moddi3.S @@ -0,0 +1,159 @@ +.file "__moddi3.s" + +// $NetBSD: moddi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + +// 64-bit signed integer remainder + +.proc __moddi3# +.align 32 +.global __moddi3# +.align 32 + +__moddi3: + +{ .mii + alloc r31=ar.pfs,3,0,0,0 + nop.i 0 + nop.i 0 +} { .mmb + + // 64-BIT SIGNED INTEGER REMAINDER BEGINS HERE + + // general register used: + // r32 - 64-bit signed integer dividend, called a below + // r33 - 64-bit signed integer divisor, called b below + // r8 - 64-bit signed integer result + // r2 - scratch register + // floating-point registers used: f6, f7, f8, f9, f10, f11, f12 + // predicate registers used: p6 + + setf.sig f12=r32 // holds a in integer form + setf.sig f7=r33 + nop.b 0 +} { .mlx + nop.m 0 + //movl r2=0x8000000000000000;; + movl r2=0xffffffffffffffff;; +} { .mfi + // get the 2's complement of b + sub r33=r0,r33 + fcvt.xf f6=f12 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xf f7=f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + setf.sig f7=r33 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (11) q = trunc(q3) + fcvt.fx.trunc.s1 f8=f8 + nop.i 0;; +} { .mfi + nop.m 0 + // (12) r = a + (-b) * q + xma.l f8=f8,f7,f12 + nop.i 0;; +} { .mib + getf.sig r8=f8 + nop.i 0 + nop.b 0 +} + + // 64-BIT SIGNED INTEGER REMAINDER ENDS HERE + +{ .mib + nop.m 0 + nop.i 0 + br.ret.sptk b0;; +} + +.endp __moddi3 diff --git a/sys/lib/libkern/arch/ia64/modsi3.S b/sys/lib/libkern/arch/ia64/modsi3.S new file mode 100644 index 000000000..1fa6d6413 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/modsi3.S @@ -0,0 +1,131 @@ +.file "__modsi3.s" + +// $NetBSD: modsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + +// 32-bit signed integer remainder + +.proc __modsi3# +.align 32 +.global __modsi3# +.align 32 + +__modsi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mii + nop.m 0 + + // 32-BIT SIGNED INTEGER REMAINDER BEGINS HERE + + // general register used: + // r32 - 32-bit signed integer dividend + // r33 - 32-bit signed integer divisor + // r8 - 32-bit signed integer result + // r2 - scratch register + // floating-point registers used: f6, f7, f8, f9, f10, f11 + // predicate registers used: p6 + + sxt4 r32=r32 + sxt4 r33=r33;; +} { .mmb + setf.sig f11=r32 + setf.sig f7=r33 + nop.b 0;; +} { .mfi + // get 2's complement of b + sub r33=r0,r33 + fcvt.xf f6=f11 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xf f7=f7 + mov r2 = 0x0ffdd;; +} { .mfi + setf.exp f9 = r2 + // (1) y0 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // (2) q0 = a * y0 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // (3) e0 = 1 - b * y0 + (p6) fnma.s1 f8=f7,f8,f1 + nop.i 0;; +} { .mfi + // 2's complement of b + setf.sig f7=r33 + // (4) q1 = q0 + e0 * q0 + (p6) fma.s1 f10=f8,f10,f10 + nop.i 0 +} { .mfi + nop.m 0 + // (5) e1 = e0 * e0 + 2^-34 + (p6) fma.s1 f8=f8,f8,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (6) q2 = q1 + e1 * q1 + (p6) fma.s1 f8=f8,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // (7) q = trunc(q2) + fcvt.fx.trunc.s1 f8=f8 + nop.i 0;; +} { .mfi + nop.m 0 + // (8) r = a + (-b) * q + xma.l f8=f8,f7,f11 + nop.i 0;; +} { .mmi + // remainder will be in the least significant 32 bits of r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 32-BIT SIGNED INTEGER REMAINDER ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __modsi3 diff --git a/sys/lib/libkern/arch/ia64/ntohl.S b/sys/lib/libkern/arch/ia64/ntohl.S new file mode 100644 index 000000000..257fb16fd --- /dev/null +++ b/sys/lib/libkern/arch/ia64/ntohl.S @@ -0,0 +1,32 @@ +/* $NetBSD: ntohl.S,v 1.1 2006/04/07 13:57:43 cherry Exp $ */ + +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#define NAME ntohl + +#include "byte_swap_4.S" diff --git a/sys/lib/libkern/arch/ia64/udivdi3.S b/sys/lib/libkern/arch/ia64/udivdi3.S new file mode 100644 index 000000000..7cb9f6e4c --- /dev/null +++ b/sys/lib/libkern/arch/ia64/udivdi3.S @@ -0,0 +1,143 @@ +.file "__udivdi3.s" + +// $NetBSD: udivdi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text +.proc __udivdi3# +.align 32 +.global __udivdi3# +.align 32 + +// 64-bit unsigned integer divide + +__udivdi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} + +{ .mmi + + // 64-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE + + setf.sig f8=r32 + setf.sig f9=r33 + nop.i 0;; +} { .mfb + nop.m 0 + fma.s1 f6=f8,f1,f0 + nop.b 0 +} { .mfb + nop.m 0 + fma.s1 f7=f9,f1,f0 + nop.b 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfb + nop.m 0 + // (11) q = trunc(q3) + fcvt.fxu.trunc.s1 f8=f8 + nop.b 0;; +} { .mmi + // quotient will be in r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 64-BIT UNSIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __udivdi3 diff --git a/sys/lib/libkern/arch/ia64/udivsi3.S b/sys/lib/libkern/arch/ia64/udivsi3.S new file mode 100644 index 000000000..51b1f1498 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/udivsi3.S @@ -0,0 +1,124 @@ +.file "__udivsi3.s" + +// $NetBSD: udivsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + +// 32-bit unsigned integer divide + +.proc __udivsi3# +.align 32 +.global __udivsi3# +.align 32 + +__udivsi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mii + nop.m 0 + + // 32-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE + + // general register used: + // r32 - 32-bit unsigned integer dividend + // r33 - 32-bit unsigned integer divisor + // r8 - 32-bit unsigned integer result + // r2 - scratch register + // floating-point registers used: f6, f7, f8, f9 + // predicate registers used: p6 + + zxt4 r32=r32 + zxt4 r33=r33;; +} { .mmb + setf.sig f6=r32 + setf.sig f7=r33 + nop.b 0;; +} { .mfi + nop.m 0 + fcvt.xf f6=f6 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xf f7=f7 + mov r2 = 0x0ffdd;; +} { .mfi + setf.exp f9 = r2 + // (1) y0 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // (2) q0 = a * y0 + (p6) fma.s1 f6=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // (3) e0 = 1 - b * y0 + (p6) fnma.s1 f7=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // (4) q1 = q0 + e0 * q0 + (p6) fma.s1 f6=f7,f6,f6 + nop.i 0 +} { .mfi + nop.m 0 + // (5) e1 = e0 * e0 + 2^-34 + (p6) fma.s1 f7=f7,f7,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (6) q2 = q1 + e1 * q1 + (p6) fma.s1 f8=f7,f6,f6 + nop.i 0;; +} { .mfi + nop.m 0 + // (7) q = trunc(q2) + fcvt.fxu.trunc.s1 f8=f8 + nop.i 0;; +} { .mmi + // quotient will be in the least significant 32 bits of r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 32-BIT UNSIGNED INTEGER DIVIDE ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __udivsi3 diff --git a/sys/lib/libkern/arch/ia64/umoddi3.S b/sys/lib/libkern/arch/ia64/umoddi3.S new file mode 100644 index 000000000..38e539d59 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/umoddi3.S @@ -0,0 +1,155 @@ +.file "__umoddi3.s" + +// $NetBSD: umoddi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + + // 64-bit unsigned integer remainder + +.proc __umoddi3# +.align 32 +.global __umoddi3# +.align 32 + +__umoddi3: + +{ .mii + alloc r31=ar.pfs,3,0,0,0 + nop.i 0 + nop.i 0 +} { .mmb + + // 64-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE + + // general register used: + // r32 - 64-bit unsigned integer dividend, called a below + // r33 - 64-bit unsigned integer divisor, called b below + // r8 - 64-bit unsigned integer result + // floating-point registers used: f6, f7, f8, f9, f10, f11, f12 + // predicate registers used: p6 + + setf.sig f12=r32 // holds a in integer form + setf.sig f7=r33 + nop.b 0;; +} { .mfi + // get 2's complement of b + sub r33=r0,r33 + fcvt.xuf.s1 f6=f12 + nop.i 0 +} { .mfi + nop.m 0 + fcvt.xuf.s1 f7=f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (1) + // y0 = 1 / b in f8 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (2) + // q0 = a * y0 in f10 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // Step (3) + // e0 = 1 - b * y0 in f9 + (p6) fnma.s1 f9=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (4) + // q1 = q0 + e0 * q0 in f10 + (p6) fma.s1 f10=f9,f10,f10 + nop.i 0 +} { .mfi + nop.m 0 + // Step (5) + // e1 = e0 * e0 in f11 + (p6) fma.s1 f11=f9,f9,f0 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (6) + // y1 = y0 + e0 * y0 in f8 + (p6) fma.s1 f8=f9,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (7) + // q2 = q1 + e1 * q1 in f9 + (p6) fma.s1 f9=f11,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (8) + // y2 = y1 + e1 * y1 in f8 + (p6) fma.s1 f8=f11,f8,f8 + nop.i 0;; +} { .mfi + nop.m 0 + // Step (9) + // r2 = a - b * q2 in f10 + (p6) fnma.s1 f10=f7,f9,f6 + nop.i 0;; +} { .mfi + // f7=-b + setf.sig f7=r33 + // Step (10) + // q3 = q2 + r2 * y2 in f8 + (p6) fma.s1 f8=f10,f8,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (11) q = trunc(q3) + fcvt.fxu.trunc.s1 f8=f8 + nop.i 0;; +} { .mfi + nop.m 0 + // (12) r = a + (-b) * q + xma.l f8=f8,f7,f12 + nop.i 0;; +} { .mib + getf.sig r8=f8 + nop.i 0 + nop.b 0 +} + + // 64-BIT UNSIGNED INTEGER REMAINDER ENDS HERE + +{ .mib + nop.m 0 + nop.i 0 + br.ret.sptk b0;; +} + +.endp __umoddi3 diff --git a/sys/lib/libkern/arch/ia64/umodsi3.S b/sys/lib/libkern/arch/ia64/umodsi3.S new file mode 100644 index 000000000..ddac05d45 --- /dev/null +++ b/sys/lib/libkern/arch/ia64/umodsi3.S @@ -0,0 +1,131 @@ +.file "__umodsi3.s" + +// $NetBSD: umodsi3.S,v 1.2 2006/04/07 14:27:33 cherry Exp $ + +//- +// Copyright (c) 2000, Intel Corporation +// All rights reserved. +// +// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache, +// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab, +// Intel Corporation. +// +// WARRANTY DISCLAIMER +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Intel Corporation is the author of this code, and requests that all +// problem reports or change requests be submitted to it directly at +// http://developer.intel.com/opensource. +// + +.section .text + +// 32-bit unsigned integer remainder + +.proc __umodsi3# +.align 32 +.global __umodsi3# +.align 32 + +__umodsi3: + +{ .mii + alloc r31=ar.pfs,2,0,0,0 + nop.i 0 + nop.i 0;; +} { .mii + nop.m 0 + + // 32-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE + + // general register used: + // r32 - 32-bit unsigned integer dividend + // r33 - 32-bit unsigned integer divisor + // r8 - 32-bit unsigned integer result + // r2 - scratch register + // floating-point registers used: f6, f7, f8, f9, f10, f11 + // predicate registers used: p6 + + zxt4 r32=r32 + zxt4 r33=r33;; +} { .mmb + setf.sig f11=r32 + setf.sig f7=r33 + nop.b 0;; +} { .mfi + nop.m 0 + fcvt.xf f6=f11 + nop.i 0 +} { .mfi + // get 2's complement of b + sub r33=r0,r33 + fcvt.xf f7=f7 + mov r2 = 0x0ffdd;; +} { .mfi + setf.exp f9 = r2 + // (1) y0 + frcpa.s1 f8,p6=f6,f7 + nop.i 0;; +} { .mfi + nop.m 0 + // (2) q0 = a * y0 + (p6) fma.s1 f10=f6,f8,f0 + nop.i 0 +} { .mfi + nop.m 0 + // (3) e0 = 1 - b * y0 + (p6) fnma.s1 f8=f7,f8,f1 + nop.i 0;; +} { .mfi + nop.m 0 + // (4) q1 = q0 + e0 * q0 + (p6) fma.s1 f10=f8,f10,f10 + nop.i 0 +} { .mfi + // get 2's complement of b + setf.sig f7=r33 + // (5) e1 = e0 * e0 + 2^-34 + (p6) fma.s1 f8=f8,f8,f9 + nop.i 0;; +} { .mfi + nop.m 0 + // (6) q2 = q1 + e1 * q1 + (p6) fma.s1 f8=f8,f10,f10 + nop.i 0;; +} { .mfi + nop.m 0 + // (7) q = trunc(q2) + fcvt.fxu.trunc.s1 f8=f8 + nop.i 0;; +} { .mfi + nop.m 0 + // (8) r = a + (-b) * q + xma.l f8=f8,f7,f11 + nop.i 0;; +} { .mmi + // remainder will be in the least significant 32 bits of r8 (if b != 0) + getf.sig r8=f8 + nop.m 0 + nop.i 0;; +} + + // 32-BIT UNSIGNED INTEGER REMAINDER ENDS HERE + +{ .mmb + nop.m 0 + nop.m 0 + br.ret.sptk b0;; +} + +.endp __umodsi3 diff --git a/sys/lib/libkern/arch/m68k/DEFS.h b/sys/lib/libkern/arch/m68k/DEFS.h new file mode 100644 index 000000000..f5c6689c3 --- /dev/null +++ b/sys/lib/libkern/arch/m68k/DEFS.h @@ -0,0 +1,3 @@ +/* $NetBSD: DEFS.h,v 1.4 1999/11/11 01:32:10 thorpej Exp $ */ + +#include diff --git a/sys/lib/libkern/arch/m68k/Makefile.inc b/sys/lib/libkern/arch/m68k/Makefile.inc new file mode 100644 index 000000000..4ab3b5f25 --- /dev/null +++ b/sys/lib/libkern/arch/m68k/Makefile.inc @@ -0,0 +1,16 @@ +# $NetBSD: Makefile.inc,v 1.30 2009/08/14 19:23:54 dsl Exp $ + +SRCS+= bswap16.S bswap32.S bswap64.S +SRCS+= memcmp.S memcpy.S memmove.S memset.S +SRCS+= strcat.S strchr.S strcmp.S +SRCS+= strcpy.S strlen.S strncmp.S strncpy.S strrchr.S +SRCS+= scanc.S skpc.S +SRCS+= htonl.S htons.S ntohl.S ntohs.S +SRCS+= ffs.S + +.if defined(MACHINE_ARCH) && (${MACHINE_ARCH} == "m68000") +SRCS+= mulsi3.S divsi3.S udivsi3.S modsi3.S umodsi3.S +random.o random.d: random.c +.else +SRCS+= random.S +.endif diff --git a/sys/lib/libkern/arch/m68k/random.S b/sys/lib/libkern/arch/m68k/random.S new file mode 100644 index 000000000..96fc68adb --- /dev/null +++ b/sys/lib/libkern/arch/m68k/random.S @@ -0,0 +1,69 @@ +/* $NetBSD: random.S,v 1.4 2009/01/06 01:24:56 pooka Exp $ */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ +#include + + .data +ASLOCAL(randseed) + .long 1 + +ENTRY(random) + movl #16807, %d0 +#ifdef PIC + lea %pc@(_GLOBAL_OFFSET_TABLE_@GOTPC), %a0 + movl _ASM_LABEL(randseed)@GOT(%a0), %d2 + mulsl (%d2), %d1:%d0 +#else + mulsl _ASM_LABEL(randseed), %d1:%d0 +#endif + lsll #1, %d0 + roxll #2, %d1 + addl %d1, %d0 + moveql #1, %d1 + addxl %d1, %d0 + lsrl #1, %d0 +#ifdef PIC + movl %d0, (%d2) +#else + movl %d0, _ASM_LABEL(randseed) +#endif + rts diff --git a/sys/lib/libkern/arch/m68k/scanc.S b/sys/lib/libkern/arch/m68k/scanc.S new file mode 100644 index 000000000..5ca5dcead --- /dev/null +++ b/sys/lib/libkern/arch/m68k/scanc.S @@ -0,0 +1,63 @@ +/* $NetBSD: scanc.S,v 1.6 2011/02/08 20:20:27 rmind Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1980, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: locore.s 1.58 91/04/22 + * @(#)locore.s 7.11 (Berkeley) 5/9/91 + */ + +#include "DEFS.h" + +/* + * Emulate fancy VAX string operations: + * scanc(count, startc, table, mask) + */ +ENTRY(scanc) + movl %sp@(4),%d0 | get length + jeq Lscdone | nothing to do, return + movl %sp@(8),%a0 | start of scan + movl %sp@(12),%a1 | table to compare with + movb %sp@(19),%d1 | and mask to use + movw %d2,%sp@- | need a scratch register + clrw %d2 | clear it out + subqw #1,%d0 | adjust for dbra +Lscloop: + movb %a0@+,%d2 | get character + movb %a1@(0,%d2:w),%d2 | get table entry + andb %d1,%d2 | mask it + dbne %d0,Lscloop | keep going til no more or non-zero + addqw #1,%d0 | overshot by one + movw %sp@+,%d2 | restore scratch +Lscdone: + rts diff --git a/sys/lib/libkern/arch/m68k/skpc.S b/sys/lib/libkern/arch/m68k/skpc.S new file mode 100644 index 000000000..7a73a46ea --- /dev/null +++ b/sys/lib/libkern/arch/m68k/skpc.S @@ -0,0 +1,57 @@ +/* $NetBSD: skpc.S,v 1.6 2011/02/08 20:20:27 rmind Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1980, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah Hdr: locore.s 1.58 91/04/22 + * @(#)locore.s 7.11 (Berkeley) 5/9/91 + */ + +#include "DEFS.h" + +/* + * Emulate fancy VAX string operations: + * skpc(mask, count, startc) + */ +ENTRY(skpc) + movl %sp@(8),%d0 | get length + jeq Lskdone | nothing to do, return + movb %sp@(7),%d1 | mask to use + movl %sp@(12),%a0 | where to start + subqw #1,%d0 | adjust for dbcc +Lskloop: + cmpb %a0@+,%d1 | compate with mask + dbne %d0,Lskloop | keep going til no more or zero + addqw #1,%d0 | overshot by one +Lskdone: + rts diff --git a/sys/lib/libkern/arch/mips/Makefile.inc b/sys/lib/libkern/arch/mips/Makefile.inc new file mode 100644 index 000000000..740ff2265 --- /dev/null +++ b/sys/lib/libkern/arch/mips/Makefile.inc @@ -0,0 +1,14 @@ +# $NetBSD: Makefile.inc,v 1.23 2010/01/20 18:13:40 pgoyette Exp $ +# +# There are likely more that we will notice when we go native + +NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c +NO_SRCS+= __main.c + +SRCS+= memchr.c memcmp.c random.c scanc.c \ + skpc.c strcat.c strcpy.c strcasecmp.c \ + strncasecmp.c strncmp.c strncpy.c strtoul.c + +SRCS+= byte_swap_2.S byte_swap_4.S byte_swap_8.S \ + ffs.S memcpy.S memset2.c memmove.S \ + strlen.S strcmp.S diff --git a/sys/lib/libkern/arch/powerpc/Makefile.inc b/sys/lib/libkern/arch/powerpc/Makefile.inc new file mode 100644 index 000000000..661af3317 --- /dev/null +++ b/sys/lib/libkern/arch/powerpc/Makefile.inc @@ -0,0 +1,15 @@ +# $NetBSD: Makefile.inc,v 1.31 2011/07/02 03:35:03 matt Exp $ + +SRCS+= bswap16.c bswap32.c +SRCS+= htonl.c htons.c ntohl.c ntohs.c +SRCS+= syncicache.c + +SRCS+= ffs.S memset.S strlen.S +SRCS+= gprsavrest.S + +# Disable the asm versions on evbppc because they break the Explora +.if ${MACHINE} == "evbppc" +memcpy.o: memcpy.c +memcmp.o: memcmp.c +memmove.o: memmove.c +.endif diff --git a/sys/lib/libkern/arch/powerpc/gprsavrest.S b/sys/lib/libkern/arch/powerpc/gprsavrest.S new file mode 100644 index 000000000..739325ec5 --- /dev/null +++ b/sys/lib/libkern/arch/powerpc/gprsavrest.S @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas of 3am Software Foundry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +__RCSID("$NetBSD: gprsavrest.S,v 1.4 2011/10/28 02:00:50 christos Exp $") + +#ifndef RESTGPR +# define RESTGPR(n) RESTOREXGPR(_restgpr_,n,_x) +# define RESTGPR_END(n) RESTOREXGPR_END(_restgpr_,n,_x) +# define SAVEGPR(n) SAVEXGPR(_savegpr_,n,) +# define SAVEGPR_END(n) SAVEXGPR_END(_savegpr_,n,) +#endif + +#define RESTOREXGPR(a,n,b) \ + .hidden a##n##b; ENTRY_NOPROFILE(a##n##b); lwz n,(-4*(32-n))(11) +#define SAVEXGPR(a,n,b) \ + .hidden a##n##b; ENTRY_NOPROFILE(a##n##b); stw n,(-4*(32-n))(11) +#ifdef _LP64 +# define SAVEXGPR_END(a,n,b) +# define RESTOREXGPR_END(a,n,b) +#else +# define SAVEXGPR_END(a,n,b) \ + .size a##n##b,.-a##n##b +# define RESTOREXGPR_END(a,n,b) \ + .size a##n##b,.-a##n##b +#endif + + RESTGPR(14) + RESTGPR(15) + RESTGPR(16) + RESTGPR(17) + RESTGPR(18) + RESTGPR(19) + RESTGPR(20) + RESTGPR(21) + RESTGPR(22) + RESTGPR(23) + RESTGPR(24) + RESTGPR(25) + RESTGPR(26) + RESTGPR(27) + RESTGPR(28) + RESTGPR(29) + RESTGPR(30) + RESTGPR(31) + lwz 0,4(11) + mtlr 0 + mr 1,11 + blr + RESTGPR_END(14) + RESTGPR_END(15) + RESTGPR_END(16) + RESTGPR_END(17) + RESTGPR_END(18) + RESTGPR_END(19) + RESTGPR_END(20) + RESTGPR_END(21) + RESTGPR_END(22) + RESTGPR_END(23) + RESTGPR_END(24) + RESTGPR_END(25) + RESTGPR_END(26) + RESTGPR_END(27) + RESTGPR_END(28) + RESTGPR_END(29) + RESTGPR_END(30) + RESTGPR_END(31) + + SAVEGPR(14) + SAVEGPR(15) + SAVEGPR(16) + SAVEGPR(17) + SAVEGPR(18) + SAVEGPR(19) + SAVEGPR(20) + SAVEGPR(21) + SAVEGPR(22) + SAVEGPR(23) + SAVEGPR(24) + SAVEGPR(25) + SAVEGPR(26) + SAVEGPR(27) + SAVEGPR(28) + SAVEGPR(29) + SAVEGPR(30) + SAVEGPR(31) + blr + SAVEGPR_END(14) + SAVEGPR_END(15) + SAVEGPR_END(16) + SAVEGPR_END(17) + SAVEGPR_END(18) + SAVEGPR_END(19) + SAVEGPR_END(20) + SAVEGPR_END(21) + SAVEGPR_END(22) + SAVEGPR_END(23) + SAVEGPR_END(24) + SAVEGPR_END(25) + SAVEGPR_END(26) + SAVEGPR_END(27) + SAVEGPR_END(28) + SAVEGPR_END(29) + SAVEGPR_END(30) + SAVEGPR_END(31) diff --git a/sys/lib/libkern/arch/powerpc/memset.S b/sys/lib/libkern/arch/powerpc/memset.S new file mode 100644 index 000000000..d6f8a8395 --- /dev/null +++ b/sys/lib/libkern/arch/powerpc/memset.S @@ -0,0 +1,99 @@ +/* $NetBSD: memset.S,v 1.7 2011/01/17 07:07:36 matt Exp $ */ + +/*- + * Copyright (C) 2003 Matt Thomas + * Copyright (C) 2001 Martin J. Laubach + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 + +/*----------------------------------------------------------------------*/ +/* + void bzero(void *b r3, size_t len r4); + void *memset(void *b r3, int c r4, size_t len r5); +*/ +/*----------------------------------------------------------------------*/ + +#define r_dst %r4 +#define r_len %r5 +#define r_tmp %r6 +#define r_val %r0 + +ENTRY(bzero) + li r_val, 0 /* Value to fill with */ + mr r_len, %r4 + b cb_memset + +ENTRY(memset) + mr r_val, %r4 /* Value to fill with */ + +cb_memset: + cmplwi r_len, 0 /* is the length 0? */ + beqlr- /* nothing to do */ + mr r_dst, %r3 + /* + * r3=start, r4=dstptr, r5=length, r0=fill-val + */ + cmplwi r_len, 6 /* more than 6 bytes? */ + bgt complex_fill /* do it the complex way */ + subi r_dst, r_dst, 1 /* presubtract for stbu */ +simple_fill: mtctr r_len /* set CTR */ +1: stbu r_val, 1(r_dst) /* update memory */ + bdnz+ 1b /* until CTR is 0 */ + blr /* return */ + +complex_fill: + rlwimi r_val, r_val, 8, 16, 23 /* word extend fill value */ + rlwimi r_val, r_val, 16, 0, 15 + andi. r_tmp, r_dst, 0x03 + beq+ word_fill /* already aligned to word? */ + andi. r_tmp, r_dst, 0x01 + beq half_fill /* aligned to halfword? */ + stb r_val, 0(r_dst) + addi r_dst, r_dst, 1 + subi r_len, r_len, 1 /* subtract byte */ + andi. r_tmp, r_dst, 0x02 + beq word_fill /* aligned to word? */ +half_fill: + sth r_val, 0(r_dst) + addi r_dst, r_dst, 2 + subi r_len, r_len, 2 /* subtract halfword */ + +word_fill: + cmplwi r_len, 4 /* we have more than 4 bytes? */ + blt- trailing_bytes /* no? finish writing */ + srwi r_tmp, r_len, 2 /* get word count */ + mtctr r_tmp + subi r_dst, r_dst, 4 +1: stwu r_val, 4(r_dst) + bdnz+ 1b + +trailing_bytes: + andi. r_len, r_len, 0x03 /* how much left? */ + beqlr+ /* nothing? return */ + addi r_dst, r_dst, 3 + b simple_fill diff --git a/sys/lib/libkern/arch/powerpc/syncicache.c b/sys/lib/libkern/arch/powerpc/syncicache.c new file mode 100644 index 000000000..e36466686 --- /dev/null +++ b/sys/lib/libkern/arch/powerpc/syncicache.c @@ -0,0 +1,132 @@ +/* $NetBSD: syncicache.c,v 1.14 2008/03/18 20:11:43 he Exp $ */ + +/* + * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank. + * Copyright (C) 1995-1997, 1999 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#if defined(_KERNEL) +#include +#include +#include +#endif +#if !defined(_STANDALONE) +#include +#endif + +#include + + +#if defined(_STANDALONE) +#ifndef CACHELINESIZE +#error "Must know the size of a cache line" +#endif +static struct cache_info _cache_info = { + CACHELINESIZE, + CACHELINESIZE, + CACHELINESIZE, + CACHELINESIZE +}; +#define CACHEINFO _cache_info +#elif defined(_KERNEL) +#define CACHEINFO (curcpu()->ci_ci) +#else +static void getcachelinesize (void); + +static int _cachelinesize = 0; + +static struct cache_info _cache_info; +#define CACHEINFO _cache_info + +static void +getcachelinesize(void) +{ + static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE }; + static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO }; + size_t clen = sizeof(_cache_info); + + if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]), + &_cache_info, &clen, NULL, 0) == 0) { + _cachelinesize = _cache_info.dcache_line_size; + return; + } + + /* Try older deprecated sysctl */ + clen = sizeof(_cachelinesize); + if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]), + &_cachelinesize, &clen, NULL, 0) < 0 + || !_cachelinesize) + abort(); + + _cache_info.dcache_size = _cachelinesize; + _cache_info.dcache_line_size = _cachelinesize; + _cache_info.icache_size = _cachelinesize; + _cache_info.icache_line_size = _cachelinesize; + /* If there is no cache, indicate we have issued the sysctl. */ + if (!_cachelinesize) + _cachelinesize = 1; +} +#endif + +void +__syncicache(void *from, size_t len) +{ + size_t l, off; + size_t linesz; + char *p; + +#if !defined(_KERNEL) && !defined(_STANDALONE) + if (!_cachelinesize) + getcachelinesize(); +#endif + + if (CACHEINFO.dcache_size > 0) { + linesz = CACHEINFO.dcache_line_size; + off = (uintptr_t)from & (linesz - 1); + l = (len + off + linesz - 1) & ~(linesz - 1); + p = (char *)from - off; + do { + __asm volatile ("dcbst 0,%0" :: "r"(p)); + p += linesz; + } while ((l -= linesz) != 0); + } + __asm volatile ("sync"); + + if (CACHEINFO.icache_size > 0 ) { + linesz = CACHEINFO.icache_line_size; + off = (uintptr_t)from & (linesz - 1); + l = (len + off + linesz - 1) & ~(linesz - 1); + p = (char *)from - off; + do { + __asm volatile ("icbi 0,%0" :: "r"(p)); + p += linesz; + } while ((l -= linesz) != 0); + } + __asm volatile ("sync; isync"); +} diff --git a/sys/lib/libkern/arch/sh3/Makefile.inc b/sys/lib/libkern/arch/sh3/Makefile.inc new file mode 100644 index 000000000..19a2fa52b --- /dev/null +++ b/sys/lib/libkern/arch/sh3/Makefile.inc @@ -0,0 +1,12 @@ +# $NetBSD: Makefile.inc,v 1.19 2011/08/04 03:20:09 uwe Exp $ + +SRCS+= ffs.S +SRCS+= memset.S +SRCS+= memmove.S memcpy.S byte_swap_2.S byte_swap_4.S byte_swap_8.S +SRCS+= ashiftrt.S ashlsi3.S ashrsi3.S lshrsi3.S movstr.S movstr_i4.S +SRCS+= movstrSI.S movstrSI12_i4.S mulsi3.S sdivsi3.S udivsi3.S + +# newer gcc uses different integer division millicode by default +SRCS+= sdivsi3_i4i.S udivsi3_i4i.S + +NO_SRCS+= bswap64.c diff --git a/sys/lib/libkern/arch/sh3/ashiftrt.S b/sys/lib/libkern/arch/sh3/ashiftrt.S new file mode 100644 index 000000000..ed5b09e0c --- /dev/null +++ b/sys/lib/libkern/arch/sh3/ashiftrt.S @@ -0,0 +1,180 @@ +/* $NetBSD: ashiftrt.S,v 1.7 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __ashiftrt_r4_0 + .hidden __ashiftrt_r4_1 + .hidden __ashiftrt_r4_2 + .hidden __ashiftrt_r4_3 + .hidden __ashiftrt_r4_4 + .hidden __ashiftrt_r4_5 + .hidden __ashiftrt_r4_6 + .hidden __ashiftrt_r4_7 + .hidden __ashiftrt_r4_8 + .hidden __ashiftrt_r4_9 + .hidden __ashiftrt_r4_10 + .hidden __ashiftrt_r4_11 + .hidden __ashiftrt_r4_12 + .hidden __ashiftrt_r4_13 + .hidden __ashiftrt_r4_14 + .hidden __ashiftrt_r4_15 + .hidden __ashiftrt_r4_16 + .hidden __ashiftrt_r4_17 + .hidden __ashiftrt_r4_18 + .hidden __ashiftrt_r4_19 + .hidden __ashiftrt_r4_20 + .hidden __ashiftrt_r4_21 + .hidden __ashiftrt_r4_22 + .hidden __ashiftrt_r4_23 + .hidden __ashiftrt_r4_24 + .hidden __ashiftrt_r4_25 + .hidden __ashiftrt_r4_26 + .hidden __ashiftrt_r4_27 + .hidden __ashiftrt_r4_28 + .hidden __ashiftrt_r4_29 + .hidden __ashiftrt_r4_30 + .hidden __ashiftrt_r4_31 +#endif /* __ELF__ */ + + +NENTRY(__ashiftrt_r4_31) + shll r4 + rts + subc r4, r4 + +ALTENTRY(__ashiftrt_r4_30) + shar r4 + +ALTENTRY(__ashiftrt_r4_29) + shar r4 + +ALTENTRY(__ashiftrt_r4_28) + shar r4 + +ALTENTRY(__ashiftrt_r4_27) + shar r4 + +ALTENTRY(__ashiftrt_r4_26) + shar r4 + +ALTENTRY(__ashiftrt_r4_25) + shar r4 + +ALTENTRY(__ashiftrt_r4_24) + shlr16 r4 + shlr8 r4 + rts + exts.b r4, r4 + +ALTENTRY(__ashiftrt_r4_23) + shar r4 + +ALTENTRY(__ashiftrt_r4_22) + shar r4 + +ALTENTRY(__ashiftrt_r4_21) + shar r4 + +ALTENTRY(__ashiftrt_r4_20) + shar r4 + +ALTENTRY(__ashiftrt_r4_19) + shar r4 + +ALTENTRY(__ashiftrt_r4_18) + shar r4 + +ALTENTRY(__ashiftrt_r4_17) + shar r4 + +ALTENTRY(__ashiftrt_r4_16) + shlr16 r4 + rts + exts.w r4, r4 + +ALTENTRY(__ashiftrt_r4_15) + swap.w r4, r4 + cmp/pz r4 + bf/s 1f + exts.w r4, r4 + rts + shll r4 +1: + sett + rts + rotcl r4 + +ALTENTRY(__ashiftrt_r4_14) + shar r4 + +ALTENTRY(__ashiftrt_r4_13) + shar r4 + +ALTENTRY(__ashiftrt_r4_12) + shar r4 + +ALTENTRY(__ashiftrt_r4_11) + shar r4 + +ALTENTRY(__ashiftrt_r4_10) + shar r4 + +ALTENTRY(__ashiftrt_r4_9) + shar r4 + +ALTENTRY(__ashiftrt_r4_8) + shar r4 + +ALTENTRY(__ashiftrt_r4_7) + shar r4 + +ALTENTRY(__ashiftrt_r4_6) + shar r4 + +ALTENTRY(__ashiftrt_r4_5) + shar r4 + +ALTENTRY(__ashiftrt_r4_4) + shar r4 + +ALTENTRY(__ashiftrt_r4_3) + shar r4 + +ALTENTRY(__ashiftrt_r4_2) + shar r4 + +ALTENTRY(__ashiftrt_r4_1) + rts + shar r4 + +ALTENTRY(__ashiftrt_r4_0) + rts + nop diff --git a/sys/lib/libkern/arch/sh3/ashlsi3.S b/sys/lib/libkern/arch/sh3/ashlsi3.S new file mode 100644 index 000000000..ea36b8863 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/ashlsi3.S @@ -0,0 +1,40 @@ +/* $NetBSD: ashlsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __ashlsi3 +#endif + + +NENTRY(__ashlsi3) + shld r5, r4 + rts + mov r4, r0 diff --git a/sys/lib/libkern/arch/sh3/ashrsi3.S b/sys/lib/libkern/arch/sh3/ashrsi3.S new file mode 100644 index 000000000..3da686a6f --- /dev/null +++ b/sys/lib/libkern/arch/sh3/ashrsi3.S @@ -0,0 +1,48 @@ +/* $NetBSD: ashrsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __ashrsi3 +#endif + + +NENTRY(__ashrsi3) + tst r5, r5 + bt noshift + + neg r5, r5 + shad r5, r4 + rts + mov r4, r0 + +noshift: + rts + mov r4, r0 diff --git a/sys/lib/libkern/arch/sh3/byte_swap_2.S b/sys/lib/libkern/arch/sh3/byte_swap_2.S new file mode 100644 index 000000000..5feede060 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/byte_swap_2.S @@ -0,0 +1,49 @@ +/* $NetBSD: byte_swap_2.S,v 1.6 2006/04/14 09:23:01 nonaka Exp $ */ + +/*- + * Copyright (C) 1999 SHIMIZU Ryo. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#undef _LOCORE +#define _LOCORE /* XXX not really, just assembly-code source */ +#include + +ENTRY(bswap16) +#if BYTE_ORDER == LITTLE_ENDIAN +ALTENTRY(ntohs) +ALTENTRY(htons) +#endif + extu.w r4, r4 + rts + swap.b r4, r0 + +#if BYTE_ORDER == BIG_ENDIAN +ENTRY(ntohs) +ALTENTRY(htons) + rts + extu.w r4, r0 +#endif diff --git a/sys/lib/libkern/arch/sh3/byte_swap_4.S b/sys/lib/libkern/arch/sh3/byte_swap_4.S new file mode 100644 index 000000000..c875483d2 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/byte_swap_4.S @@ -0,0 +1,50 @@ +/* $NetBSD: byte_swap_4.S,v 1.5 2006/04/14 09:23:01 nonaka Exp $ */ + +/*- + * Copyright (C) 1999 SHIMIZU Ryo. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#undef _LOCORE +#define _LOCORE /* XXX not really, just assembly-code source */ +#include + +ENTRY(bswap32) +#if BYTE_ORDER == LITTLE_ENDIAN +ALTENTRY(ntohl) +ALTENTRY(htonl) +#endif + swap.b r4,r0 + swap.w r0,r0 + rts + swap.b r0,r0 + +#if BYTE_ORDER == BIG_ENDIAN +ENTRY(ntohl) +ALTENTRY(htonl) + rts + mov r4, r0 +#endif diff --git a/sys/lib/libkern/arch/sh3/byte_swap_8.S b/sys/lib/libkern/arch/sh3/byte_swap_8.S new file mode 100644 index 000000000..5714b63be --- /dev/null +++ b/sys/lib/libkern/arch/sh3/byte_swap_8.S @@ -0,0 +1,43 @@ +/* $NetBSD: byte_swap_8.S,v 1.2 2005/12/11 12:24:44 christos Exp $ */ + +/* + * Copyright (c) 2003 Valeriy E. Ushakov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#if defined(LIBC_SCCS) && !defined(lint) + RCSID("$NetBSD: byte_swap_8.S,v 1.2 2005/12/11 12:24:44 christos Exp $") +#endif + +ENTRY(bswap64) + swap.b r4,r4 + swap.b r5,r5 + swap.w r4,r4 + swap.w r5,r5 + swap.b r4,r1 + rts + swap.b r5,r0 diff --git a/sys/lib/libkern/arch/sh3/lshrsi3.S b/sys/lib/libkern/arch/sh3/lshrsi3.S new file mode 100644 index 000000000..42c0cab3c --- /dev/null +++ b/sys/lib/libkern/arch/sh3/lshrsi3.S @@ -0,0 +1,48 @@ +/* $NetBSD: lshrsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __lshrsi3 +#endif + + +NENTRY(__lshrsi3) + tst r5, r5 + bt noshift + + neg r5, r5 + shld r5, r4 + rts + mov r4, r0 + +noshift: + rts + mov r4, r0 diff --git a/sys/lib/libkern/arch/sh3/movstr.S b/sys/lib/libkern/arch/sh3/movstr.S new file mode 100644 index 000000000..7786b2379 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/movstr.S @@ -0,0 +1,99 @@ +/* $NetBSD: movstr.S,v 1.9 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __movstr, __movmem +#endif + + +NENTRY(__movstr) + mov #16, r0 + cmp/gt r0, r6 + bf loop2 + + .align 2 +loop1: + mov.l @r5+, r0 + mov.l r0, @r4 + mov.l @r5+, r0 + mov.l r0, @(4, r4) + mov.l @r5+, r0 + mov.l r0, @(8, r4) + mov.l @r5+, r0 + mov.l r0, @(12, r4) + mov.l @r5+, r0 + mov.l r0, @(16, r4) + mov.l @r5+, r0 + mov.l r0, @(20, r4) + mov.l @r5+, r0 + mov.l r0, @(24, r4) + mov.l @r5+, r0 + mov.l r0, @(28, r4) + mov.l @r5+, r0 + mov.l r0, @(32, r4) + mov.l @r5+, r0 + mov.l r0, @(36, r4) + mov.l @r5+, r0 + mov.l r0, @(40, r4) + mov.l @r5+, r0 + mov.l r0, @(44, r4) + mov.l @r5+, r0 + mov.l r0, @(48, r4) + mov.l @r5+, r0 + mov.l r0, @(52, r4) + mov.l @r5+, r0 + mov.l r0, @(56, r4) + mov.l @r5+, r0 + mov.l r0, @(60, r4) + add #-16, r6 + add #64, r4 + + mov #16, r0 + cmp/gt r0, r6 + bt loop1 + +loop2: + add #-32, r6 + .align 2 +1: + mov.l @r5+, r0 + mov.l r0, @r4 + add #4, r4 + add #1, r6 + tst r6, r6 + bf 1b + + rts + nop + + +/* gcc4 uses movmem, older versions use movstr */ +STRONG_ALIAS(__movmem, __movstr) diff --git a/sys/lib/libkern/arch/sh3/movstrSI.S b/sys/lib/libkern/arch/sh3/movstrSI.S new file mode 100644 index 000000000..75b410469 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/movstrSI.S @@ -0,0 +1,119 @@ +/* $NetBSD: movstrSI.S,v 1.8 2009/01/07 22:15:18 uwe Exp $ */ + +/* + * Copyright (c) 2000 SHIMIZU Ryo. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __movstrSI4, __movmemSI4 + .hidden __movstrSI8, __movmemSI8 + .hidden __movstrSI12, __movmemSI12 + .hidden __movstrSI16, __movmemSI16 + .hidden __movstrSI20, __movmemSI20 + .hidden __movstrSI24, __movmemSI24 + .hidden __movstrSI28, __movmemSI28 + .hidden __movstrSI32, __movmemSI32 + .hidden __movstrSI36, __movmemSI36 + .hidden __movstrSI40, __movmemSI40 + .hidden __movstrSI44, __movmemSI44 + .hidden __movstrSI48, __movmemSI48 + .hidden __movstrSI52, __movmemSI52 + .hidden __movstrSI56, __movmemSI56 + .hidden __movstrSI60, __movmemSI60 + .hidden __movstrSI64, __movmemSI64 +#endif + + +NENTRY(__movstrSI64) + mov.l @(60, r5), r0 + mov.l r0, @(60, r4) +ALTENTRY(__movstrSI60) + mov.l @(56, r5), r0 + mov.l r0, @(56, r4) +ALTENTRY(__movstrSI56) + mov.l @(52, r5), r0 + mov.l r0, @(52, r4) +ALTENTRY(__movstrSI52) + mov.l @(48, r5), r0 + mov.l r0, @(48, r4) +ALTENTRY(__movstrSI48) + mov.l @(44, r5), r0 + mov.l r0, @(44, r4) +ALTENTRY(__movstrSI44) + mov.l @(40, r5), r0 + mov.l r0, @(40, r4) +ALTENTRY(__movstrSI40) + mov.l @(36, r5), r0 + mov.l r0, @(36, r4) +ALTENTRY(__movstrSI36) + mov.l @(32, r5), r0 + mov.l r0, @(32, r4) +ALTENTRY(__movstrSI32) + mov.l @(28, r5), r0 + mov.l r0, @(28, r4) +ALTENTRY(__movstrSI28) + mov.l @(24, r5), r0 + mov.l r0, @(24, r4) +ALTENTRY(__movstrSI24) + mov.l @(20, r5), r0 + mov.l r0, @(20, r4) +ALTENTRY(__movstrSI20) + mov.l @(16, r5), r0 + mov.l r0, @(16, r4) +ALTENTRY(__movstrSI16) + mov.l @(12, r5), r0 + mov.l r0, @(12, r4) +ALTENTRY(__movstrSI12) + mov.l @(8, r5), r0 + mov.l r0, @(8, r4) +ALTENTRY(__movstrSI8) + mov.l @(4, r5), r0 + mov.l r0, @(4, r4) +ALTENTRY(__movstrSI4) + mov.l @r5, r0 + rts + mov.l r0, @r4 + + +/* gcc4 uses movmem, older versions use movstr */ +STRONG_ALIAS(__movmemSI4, __movstrSI4) +STRONG_ALIAS(__movmemSI8, __movstrSI8) +STRONG_ALIAS(__movmemSI12, __movstrSI12) +STRONG_ALIAS(__movmemSI16, __movstrSI16) +STRONG_ALIAS(__movmemSI20, __movstrSI20) +STRONG_ALIAS(__movmemSI24, __movstrSI24) +STRONG_ALIAS(__movmemSI28, __movstrSI28) +STRONG_ALIAS(__movmemSI32, __movstrSI32) +STRONG_ALIAS(__movmemSI36, __movstrSI36) +STRONG_ALIAS(__movmemSI40, __movstrSI40) +STRONG_ALIAS(__movmemSI44, __movstrSI44) +STRONG_ALIAS(__movmemSI48, __movstrSI48) +STRONG_ALIAS(__movmemSI52, __movstrSI52) +STRONG_ALIAS(__movmemSI56, __movstrSI56) +STRONG_ALIAS(__movmemSI60, __movstrSI60) +STRONG_ALIAS(__movmemSI64, __movstrSI64) diff --git a/sys/lib/libkern/arch/sh3/movstrSI12_i4.S b/sys/lib/libkern/arch/sh3/movstrSI12_i4.S new file mode 100644 index 000000000..2ef09c450 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/movstrSI12_i4.S @@ -0,0 +1,21 @@ +/* $NetBSD: movstrSI12_i4.S,v 1.2 2009/01/07 22:15:18 uwe Exp $ */ + +#include + + +#ifdef __ELF__ + .hidden __movstrSI12_i4, __movmemSI12_i4 +#endif + + +NENTRY(__movstrSI12_i4) + mov.l @r5, r0 + mov.l @(4, r5), r1 + mov.l @(8, r5), r2 + mov.l r0, @r4 + mov.l r1, @(4, r4) + rts + mov.l r2, @(8, r4) + +/* gcc4 uses movmem, older versions use movstr */ +STRONG_ALIAS(__movmemSI12_i4, __movstrSI12_i4) diff --git a/sys/lib/libkern/arch/sh3/movstr_i4.S b/sys/lib/libkern/arch/sh3/movstr_i4.S new file mode 100644 index 000000000..24c47e357 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/movstr_i4.S @@ -0,0 +1,80 @@ +/* $NetBSD: movstr_i4.S,v 1.6 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 2002 SHIMIZU Ryo. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __movstr_i4_odd, __movmem_i4_odd + .hidden __movstr_i4_even, __movmem_i4_even +#endif + + +NENTRY(__movstr_i4_odd) + add #-8,r4 + nop +odd_loop: + mov.l @r5+,r0 + add #8,r4 + mov.l @r5+,r1 + dt r6 + mov.l r0,@(0,r4) + bf/s odd_loop + mov.l r1,@(4,r4) + + mov.l @r5+,r0 + mov.l @r5+,r1 + mov.l @r5+,r2 + mov.l r0,@(8,r4) + mov.l r1,@(12,r4) + rts + mov.l r2,@(16,r4) + + +NENTRY(__movstr_i4_even) + add #-8,r4 + nop +even_loop: + mov.l @r5+,r0 + add #8,r4 + mov.l @r5+,r1 + dt r6 + mov.l r0,@(0,r4) + bf/s even_loop + mov.l r1,@(4,r4) + + mov.l @r5+,r0 + mov.l @r5+,r1 + mov.l r0,@(8,r4) + rts + mov.l r1,@(12,r4) + + +/* gcc4 uses movmem, older versions use movstr */ +STRONG_ALIAS(__movmem_i4_odd, __movstr_i4_odd) +STRONG_ALIAS(__movmem_i4_even, __movstr_i4_even) diff --git a/sys/lib/libkern/arch/sh3/mulsi3.S b/sys/lib/libkern/arch/sh3/mulsi3.S new file mode 100644 index 000000000..9f6e9c05e --- /dev/null +++ b/sys/lib/libkern/arch/sh3/mulsi3.S @@ -0,0 +1,40 @@ +/* $NetBSD: mulsi3.S,v 1.6 2009/01/07 22:15:18 uwe Exp $ */ + +/*- + * Copyright (C) 1999 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + + +#ifdef __ELF__ + .hidden __mulsi3 +#endif + + +NENTRY(__mulsi3) + mul.l r4, r5 + rts + sts macl, r0 diff --git a/sys/lib/libkern/arch/sh3/sdivsi3.S b/sys/lib/libkern/arch/sh3/sdivsi3.S new file mode 100644 index 000000000..e9723c9db --- /dev/null +++ b/sys/lib/libkern/arch/sh3/sdivsi3.S @@ -0,0 +1,92 @@ +/* $NetBSD: sdivsi3.S,v 1.12 2011/08/05 01:59:39 uwe Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: sdivsi3.S,v 1.12 2011/08/05 01:59:39 uwe Exp $") +#endif + +/* + * IMPOTANT: This function is special. + * + * This function is an auxiliary "millicode" function that is + * referenced by the code generated by gcc for signed integer + * division. But gcc does NOT treat a call to this function as an + * ordinary function call - it can clobber only R1, R2 and R3. + * + * See the definition of "divsi3_i1" in gcc/config/sh/sh.md + * + * As the consequence this function cannot be called via any + * indirection that assumes normal calling convention: + * + * . cannot have _PROF_PROLOGUE + * . cannot be called via PLT (not relevant for kernel) + */ + + +#ifdef __ELF__ + .hidden __sdivsi3 +#endif + + +/* r0 <= r4 / r5 */ +NENTRY(__sdivsi3) + mov r4, r0 + mov r5, r1 + + tst r1, r1 + bt .L_div_by_zero + + mov #0, r2 + div0s r2, r0 + subc r3, r3 + subc r2, r0 + div0s r1, r3 +#define DIVSTEP rotcl r0; div1 r1, r3 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r0 + + rts + addc r2, r0 + +.L_div_by_zero: + rts + mov #0, r0 diff --git a/sys/lib/libkern/arch/sh3/sdivsi3_i4i.S b/sys/lib/libkern/arch/sh3/sdivsi3_i4i.S new file mode 100644 index 000000000..3ea32e1dd --- /dev/null +++ b/sys/lib/libkern/arch/sh3/sdivsi3_i4i.S @@ -0,0 +1,108 @@ +/* $NetBSD: sdivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: sdivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $") +#endif + +/* + * IMPOTANT: This function is special. + * + * This function is an auxiliary "millicode" function that is + * referenced by the code generated by gcc for signed integer + * division. But gcc does NOT treat a call to this function as an + * ordinary function call - it can clobber only R1, MACL and MACH. + * + * See the definition of "divsi3_i4_int" in gcc/config/sh/sh.md + * + * As the consequence this function cannot be called via any + * indirection that assumes normal calling convention: + * + * . cannot have _PROF_PROLOGUE + * . cannot be called via PLT (not relevant for kernel) + * + * XXX: uwe: Older gcc used __sdivsi3; newer uses __sdivsi3_i4i - a + * heavily tuned version that is NOT compatible with __sdivsi3 because + * it clobbers different registers. We don't want to link the kernel + * against libgcc and we don't have resources to write heavily tuned + * version ourselves, so clone __sdivsi3 but adjust the code to + * conform to the __sdivsi3_i4i clobber spec. + */ + + +#ifdef __ELF__ + .hidden __sdivsi3_i4i +#endif + + +/* r0 <= r4 / r5 */ +NENTRY(__sdivsi3_i4i) + mov r4, r0 + mov r5, r1 + + tst r1, r1 + bt .L_div_by_zero + + !! this version cannot clobber r2 and r3, but can clobber macl/mach + lds r2, macl + lds r3, mach + + mov #0, r2 + div0s r2, r0 + subc r3, r3 + subc r2, r0 + div0s r1, r3 +#define DIVSTEP rotcl r0; div1 r1, r3 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r0 + + addc r2, r0 + + sts mach, r3 + sts macl, r2 + + rts + nop + +.L_div_by_zero: + rts + mov #0, r0 diff --git a/sys/lib/libkern/arch/sh3/udivsi3.S b/sys/lib/libkern/arch/sh3/udivsi3.S new file mode 100644 index 000000000..18a65e5a0 --- /dev/null +++ b/sys/lib/libkern/arch/sh3/udivsi3.S @@ -0,0 +1,86 @@ +/* $NetBSD: udivsi3.S,v 1.11 2011/08/05 01:59:39 uwe Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: udivsi3.S,v 1.11 2011/08/05 01:59:39 uwe Exp $") +#endif + +/* + * IMPOTANT: This function is special. + * + * This function is an auxiliary "millicode" function that is + * referenced by the code generated by gcc for unsigned integer + * division. But gcc does NOT treat a call to this function as an + * ordinary function call - it can clobber only R4. + * + * See the definition of "udivsi3_i1" in gcc/config/sh/sh.md + * + * As the consequence this function cannot be called via any + * indirection that assumes normal calling convention: + * + * . cannot have _PROF_PROLOGUE + * . cannot be called via PLT (not relevant for kernel) + */ + + +#ifdef __ELF__ + .hidden __udivsi3 +#endif + + +/* r0 <= r4 / r5 */ +NENTRY(__udivsi3) + tst r5, r5 + bt .L_div_by_zero + + mov #0, r0 + div0u +#define DIVSTEP rotcl r4; div1 r5, r0 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r4 + + rts + mov r4, r0 + +.L_div_by_zero: + rts + mov #0, r0 diff --git a/sys/lib/libkern/arch/sh3/udivsi3_i4i.S b/sys/lib/libkern/arch/sh3/udivsi3_i4i.S new file mode 100644 index 000000000..0e9cb6e1f --- /dev/null +++ b/sys/lib/libkern/arch/sh3/udivsi3_i4i.S @@ -0,0 +1,94 @@ +/* $NetBSD: udivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include +#if defined(LIBC_SCCS) + RCSID("$NetBSD: udivsi3_i4i.S,v 1.2 2011/08/05 02:00:25 uwe Exp $") +#endif + +/* + * IMPOTANT: This function is special. + * + * This function is an auxiliary "millicode" function that is + * referenced by the code generated by gcc for unsigned integer + * division. But gcc does NOT treat a call to this function as an + * ordinary function call - it can clobber only R1, MACL and MACH. + * + * See the definition of "udivsi3_i4_int" in gcc/config/sh/sh.md + * + * As the consequence this function cannot be called via any + * indirection that assumes normal calling convention: + * + * . cannot have _PROF_PROLOGUE + * . cannot be called via PLT (not relevant for kernel) + * + * XXX: uwe: Older gcc used __udivsi3; newer uses __udivsi3_i4i - a + * heavily tuned version that is NOT compatible with __udivsi3 because + * it clobbers different registers. We don't want to link the kernel + * against libgcc and we don't have resources to write heavily tuned + * version ourselves, so clone __udivsi3 but adjust the code to + * conform to the __udivsi3_i4i clobber spec. + */ + + +#ifdef __ELF__ + .hidden __udivsi3_i4i +#endif + + +/* r0 <= r4 / r5 */ +NENTRY(__udivsi3_i4i) + tst r5, r5 + bt .L_div_by_zero + + mov r4, r1 ! cannot clobber r4 in this version + mov #0, r0 + div0u +#define DIVSTEP rotcl r1; div1 r5, r0 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r1 + + rts + mov r1, r0 + +.L_div_by_zero: + rts + mov #0, r0 diff --git a/sys/lib/libkern/arch/sparc/Makefile.inc b/sys/lib/libkern/arch/sparc/Makefile.inc new file mode 100644 index 000000000..c31bdb79d --- /dev/null +++ b/sys/lib/libkern/arch/sparc/Makefile.inc @@ -0,0 +1,40 @@ +# $NetBSD: Makefile.inc,v 1.34 2009/08/14 19:23:54 dsl Exp $ + +SRCS+= ffs.S +SRCS+= memset.S +SRCS+= strlen.S +SRCS+= htonl.S htons.S ntohl.S ntohs.S +SRCS+= random.S + +SRCS+= bswap16.c bswap32.c + +SRCS+= mul.S umul.S saveregs.S + +# `source' files built from m4 source +# the name `div.o' is taken for the ANSI C `div' function, hence sdiv here +SRCS+= rem.S sdiv.S udiv.S urem.S +CLEANFILES+=rem.S sdiv.S udiv.S urem.S + +.SUFFIXES: .m4 + +.PATH.m4: ${KERNDIR}/arch/${MACHINE_ARCH} + +sdiv.S: divrem.m4 + echo 'building ${.TARGET} from ${.ALLSRC}' + (echo "define(NAME,\`.div')define(OP,\`div')define(S,\`true')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +udiv.S: divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`.udiv')define(OP,\`div')define(S,\`false')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +rem.S: divrem.m4 + echo 'building ${.TARGET} from ${.ALLSRC}' + (echo "define(NAME,\`.rem')define(OP,\`rem')define(S,\`true')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +urem.S: divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`.urem')define(OP,\`rem')define(S,\`false')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} diff --git a/sys/lib/libkern/arch/sparc/divrem.m4 b/sys/lib/libkern/arch/sparc/divrem.m4 new file mode 100644 index 000000000..26b5fa583 --- /dev/null +++ b/sys/lib/libkern/arch/sparc/divrem.m4 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp + * $NetBSD: divrem.m4,v 1.9 2011/06/13 03:23:53 mrg Exp $ + */ + +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +#if defined(LIBC_SCCS) && !defined(lint) + .asciz "@(#)divrem.m4 8.1 (Berkeley) 6/4/93" +#endif /* LIBC_SCCS and not lint */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * NAME name of function to generate + * OP OP=div => %o0 / %o1; OP=rem => %o0 % %o1 + * S S=true => signed; S=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TWOSUPN 2^N, for label generation (m4 exponentiation currently broken) + * TOPBITS number of bits in the top `decade' of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + +define(N, `4') +define(TWOSUPN, `16') +define(WORDSIZE, `32') +define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N))) + +define(dividend, `%o0') +define(divisor, `%o1') +define(Q, `%o2') +define(R, `%o3') +define(ITER, `%o4') +define(V, `%o5') + +/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */ +define(T, `%g1') +define(SC, `%g5') +ifelse(S, `true', `define(SIGN, `%g6')') + +/* + * This is the recursive definition for developing quotient digits. + * + * Parameters: + * $1 the current depth, 1 <= $1 <= N + * $2 the current accumulation of quotient bits + * N max depth + * + * We add a new bit to $2 and either recurse or insert the bits in + * the quotient. R, Q, and V are inputs and outputs as defined above; + * the condition codes are expected to reflect the input R, and are + * modified to reflect the output R. + */ +define(DEVELOP_QUOTIENT_BITS, +` ! depth $1, accumulated bits $2 + bl L.$1.eval(TWOSUPN+$2) + srl V,1,V + ! remainder is positive + subcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2+1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')') +L.$1.eval(TWOSUPN+$2): + ! remainder is negative + addcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2-1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')') + ifelse($1, 1, `9:')') + +#include +#include + +FUNC(NAME) +ifelse(S, `true', +` ! compute sign of result; if neither is negative, no problem + orcc divisor, dividend, %g0 ! either negative? + bge 2f ! no, go do the divide + ifelse(OP, `div', + `xor divisor, dividend, SIGN', + `mov dividend, SIGN') ! compute sign in any case + tst divisor + bge 1f + tst dividend + ! divisor is definitely negative; dividend might also be negative + bge 2f ! if dividend not negative... + neg divisor ! in any case, make divisor nonneg +1: ! dividend is negative, divisor is nonnegative + neg dividend ! make dividend nonnegative +2: +') + ! Ready to divide. Compute size of quotient; scale comparand. + orcc divisor, %g0, V + bnz 1f + mov dividend, R + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + t ST_DIV0 + retl + clr %o0 + +1: + cmp R, V ! if divisor exceeds dividend, done + blu Lgot_result ! (and algorithm fails otherwise) + clr Q + sethi %hi(1 << (WORDSIZE - TOPBITS - 1)), T + cmp R, T + blu Lnot_really_big + clr ITER + + ! `Here the dividend is >= 2^(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R.' + 1: + cmp V, T + bgeu 3f + mov 1, SC + sll V, N, V + b 1b + inc ITER + + ! Now compute SC. + 2: addcc V, V, V + bcc Lnot_too_big + inc SC + + ! We get here if the divisor overflowed while shifting. + ! This means that R has the high-order bit set. + ! Restore V and subtract from R. + sll T, TOPBITS, T ! high order bit + srl V, 1, V ! rest of V + add V, T, V + b Ldo_single_div + dec SC + + Lnot_too_big: + 3: cmp V, R + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! V > R: went too far: back up 1 step + ! srl V, 1, V + ! dec SC + ! do single-bit divide steps + ! + ! We have to be careful here. We know that R >= V, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if R >= 0. Because both R and V may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + deccc SC + bl Lend_regular_divide + nop + sub R, V, R + mov 1, Q + b Lend_single_divloop + nop + Lsingle_divloop: + sll Q, 1, Q + bl 1f + srl V, 1, V + ! R >= 0 + sub R, V, R + b 2f + inc Q + 1: ! R < 0 + add R, V, R + dec Q + 2: + Lend_single_divloop: + deccc SC + bge Lsingle_divloop + tst R + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll V, N, V + cmp V, R + bleu 1b + inccc ITER + be Lgot_result + dec ITER + + tst R ! set up for initial iteration +Ldivloop: + sll Q, N, Q + DEVELOP_QUOTIENT_BITS(1, 0) +Lend_regular_divide: + deccc ITER + bge Ldivloop + tst R + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) +ifelse(OP, `div', +` dec Q +', ` add R, divisor, R +') + +Lgot_result: +ifelse(S, `true', +` ! check to see if answer should be < 0 + tst SIGN + bl,a 1f + ifelse(OP, `div', `neg Q', `neg R') +1:') + retl + ifelse(OP, `div', `mov Q, %o0', `mov R, %o0') diff --git a/sys/lib/libkern/arch/sparc/random.S b/sys/lib/libkern/arch/sparc/random.S new file mode 100644 index 000000000..d4d2bcc91 --- /dev/null +++ b/sys/lib/libkern/arch/sparc/random.S @@ -0,0 +1,104 @@ +/* $NetBSD: random.S,v 1.3 2009/01/05 01:16:09 pooka Exp $ */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ +#include + + .data +randseed: + .long 1 + + .text +ENTRY(random) + sethi %hi(16807), %o1 + wr %o1, %lo(16807), %y +#ifdef PIC + PIC_PROLOGUE(%o5, %o2) + set randseed, %g1 + ld [%o5 + %g1], %g1 + ld [%g1], %o0 +#else + sethi %hi(randseed), %g1 + ld [%g1 + %lo(randseed)], %o0 +#endif + andcc %g0, 0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %g0, %o2 + rd %y, %o3 + srl %o2, 16, %o1 + set 0xffff, %o4 + and %o4, %o2, %o0 + sll %o0, 15, %o0 + srl %o3, 17, %o3 + or %o3, %o0, %o0 + addcc %o0, %o1, %o0 + bneg 1f + sethi %hi(0x7fffffff), %o1 + retl +#ifdef PIC + st %o0, [%g1] +#else + st %o0, [%g1 + %lo(randseed)] +#endif +1: + or %o1, %lo(0x7fffffff), %o1 + add %o0, 1, %o0 + and %o1, %o0, %o0 + retl +#ifdef PIC + st %o0, [%g1] +#else + st %o0, [%g1 + %lo(randseed)] +#endif diff --git a/sys/lib/libkern/arch/sparc64/DEFS.h b/sys/lib/libkern/arch/sparc64/DEFS.h new file mode 100644 index 000000000..c9686f383 --- /dev/null +++ b/sys/lib/libkern/arch/sparc64/DEFS.h @@ -0,0 +1,39 @@ +/* $NetBSD: DEFS.h,v 1.3 2005/12/11 12:24:45 christos Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)DEFS.h 8.1 (Berkeley) 6/4/93 + */ + +#include + diff --git a/sys/lib/libkern/arch/sparc64/Makefile.inc b/sys/lib/libkern/arch/sparc64/Makefile.inc new file mode 100644 index 000000000..42094cf03 --- /dev/null +++ b/sys/lib/libkern/arch/sparc64/Makefile.inc @@ -0,0 +1,36 @@ +# $NetBSD: Makefile.inc,v 1.10 2009/08/14 19:23:55 dsl Exp $ + +SRCS+= ffs.S +SRCS+= strlen.S +SRCS+= htonl.S htons.S ntohl.S ntohs.S +SRCS+= random.S + +SRCS+= bswap16.c bswap32.c + +SRCS+= umul.S mul.S rem.S sdiv.S udiv.S umul.S urem.S +SRCS+= mul.S saveregs.S umul.S + +# `source' files built from m4 source +# the name `div.o' is taken for the ANSI C `div' function, hence sdiv here +SRCS+= rem.S sdiv.S udiv.S urem.S +CLEANFILES+=rem.S sdiv.S udiv.S urem.S + +sdiv.S: $M/divrem.m4 + echo 'building ${.TARGET} from ${.ALLSRC}' + (echo "define(NAME,\`.div')define(OP,\`div')define(S,\`true')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +udiv.S: $M/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`.udiv')define(OP,\`div')define(S,\`false')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +rem.S: $M/divrem.m4 + echo 'building ${.TARGET} from ${.ALLSRC}' + (echo "define(NAME,\`.rem')define(OP,\`rem')define(S,\`true')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} + +urem.S: $M/divrem.m4 + @echo 'building ${.TARGET} from ${.ALLSRC}' + @(echo "define(NAME,\`.urem')define(OP,\`rem')define(S,\`false')"; \ + cat ${.ALLSRC}) | ${TOOL_M4} > ${.TARGET} diff --git a/sys/lib/libkern/arch/sparc64/divrem.m4 b/sys/lib/libkern/arch/sparc64/divrem.m4 new file mode 100644 index 000000000..03063cad2 --- /dev/null +++ b/sys/lib/libkern/arch/sparc64/divrem.m4 @@ -0,0 +1,273 @@ +/* $NetBSD: divrem.m4,v 1.5 2005/12/11 12:24:45 christos Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Header: divrem.m4,v 1.4 92/06/25 13:23:57 torek Exp + */ + +#include +#include + +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +#if defined(LIBC_SCCS) + RCSID("$NetBSD: divrem.m4,v 1.5 2005/12/11 12:24:45 christos Exp $") +#endif + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * NAME name of function to generate + * OP OP=div => %o0 / %o1; OP=rem => %o0 % %o1 + * S S=true => signed; S=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TWOSUPN 2^N, for label generation (m4 exponentiation currently broken) + * TOPBITS number of bits in the top `decade' of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + +define(N, `4') +define(TWOSUPN, `16') +define(WORDSIZE, `32') +define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N))) + +define(dividend, `%o0') +define(divisor, `%o1') +define(Q, `%o2') +define(R, `%o3') +define(ITER, `%o4') +define(V, `%o5') + +/* m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d */ +define(T, `%g1') +define(SC, `%g5') +ifelse(S, `true', `define(SIGN, `%g6')') + +/* + * This is the recursive definition for developing quotient digits. + * + * Parameters: + * $1 the current depth, 1 <= $1 <= N + * $2 the current accumulation of quotient bits + * N max depth + * + * We add a new bit to $2 and either recurse or insert the bits in + * the quotient. R, Q, and V are inputs and outputs as defined above; + * the condition codes are expected to reflect the input R, and are + * modified to reflect the output R. + */ +define(DEVELOP_QUOTIENT_BITS, +` ! depth $1, accumulated bits $2 + bl L.$1.eval(TWOSUPN+$2) + srl V,1,V + ! remainder is positive + subcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2+1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')') +L.$1.eval(TWOSUPN+$2): + ! remainder is negative + addcc R,V,R + ifelse($1, N, + ` b 9f + add Q, ($2*2-1), Q + ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')') + ifelse($1, 1, `9:')') + +FUNC(NAME) +ifelse(S, `true', +` ! compute sign of result; if neither is negative, no problem + orcc divisor, dividend, %g0 ! either negative? + bge 2f ! no, go do the divide + ifelse(OP, `div', + `xor divisor, dividend, SIGN', + `mov dividend, SIGN') ! compute sign in any case + tst divisor + bge 1f + tst dividend + ! divisor is definitely negative; dividend might also be negative + bge 2f ! if dividend not negative... + neg divisor ! in any case, make divisor nonneg +1: ! dividend is negative, divisor is nonnegative + neg dividend ! make dividend nonnegative +2: +') + ! Ready to divide. Compute size of quotient; scale comparand. + orcc divisor, %g0, V + bnz 1f + mov dividend, R + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + t ST_DIV0 + retl + clr %o0 + +1: + cmp R, V ! if divisor exceeds dividend, done + blu Lgot_result ! (and algorithm fails otherwise) + clr Q + sethi %hi(1 << (WORDSIZE - TOPBITS - 1)), T + cmp R, T + blu Lnot_really_big + clr ITER + + ! `Here the dividend is >= 2^(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R.' + 1: + cmp V, T + bgeu 3f + mov 1, SC + sll V, N, V + b 1b + inc ITER + + ! Now compute SC. + 2: addcc V, V, V + bcc Lnot_too_big + inc SC + + ! We get here if the divisor overflowed while shifting. + ! This means that R has the high-order bit set. + ! Restore V and subtract from R. + sll T, TOPBITS, T ! high order bit + srl V, 1, V ! rest of V + add V, T, V + b Ldo_single_div + dec SC + + Lnot_too_big: + 3: cmp V, R + blu 2b + nop + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! V > R: went too far: back up 1 step + ! srl V, 1, V + ! dec SC + ! do single-bit divide steps + ! + ! We have to be careful here. We know that R >= V, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if R >= 0. Because both R and V may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + deccc SC + bl Lend_regular_divide + nop + sub R, V, R + mov 1, Q + b Lend_single_divloop + nop + Lsingle_divloop: + sll Q, 1, Q + bl 1f + srl V, 1, V + ! R >= 0 + sub R, V, R + b 2f + inc Q + 1: ! R < 0 + add R, V, R + dec Q + 2: + Lend_single_divloop: + deccc SC + bge Lsingle_divloop + tst R + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll V, N, V + cmp V, R + bleu 1b + inccc ITER + be Lgot_result + dec ITER + + tst R ! set up for initial iteration +Ldivloop: + sll Q, N, Q + DEVELOP_QUOTIENT_BITS(1, 0) +Lend_regular_divide: + deccc ITER + bge Ldivloop + tst R + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) +ifelse(OP, `div', +` dec Q +', ` add R, divisor, R +') + +Lgot_result: +ifelse(S, `true', +` ! check to see if answer should be < 0 + tst SIGN + bl,a 1f + ifelse(OP, `div', `neg Q', `neg R') +1:') + retl + ifelse(OP, `div', `mov Q, %o0', `mov R, %o0') diff --git a/sys/lib/libkern/arch/sparc64/random.S b/sys/lib/libkern/arch/sparc64/random.S new file mode 100644 index 000000000..86aeeb359 --- /dev/null +++ b/sys/lib/libkern/arch/sparc64/random.S @@ -0,0 +1,104 @@ +/* $NetBSD: random.S,v 1.3 2009/01/05 01:16:09 pooka Exp $ */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ +#include + + .data +randseed: + .long 1 + + .text +ENTRY(random) + sethi %hi(16807), %o1 + wr %o1, %lo(16807), %y +#ifdef PIC + PIC_PROLOGUE(%o5, %o2) + set randseed, %g1 + ldx [%o5 + %g1], %g1 + ld [%g1], %o0 +#else + sethi %hi(randseed), %g1 + ld [%g1 + %lo(randseed)], %o0 +#endif + andcc %g0, 0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %o0, %o2 + mulscc %o2, %g0, %o2 + rd %y, %o3 + srl %o2, 16, %o1 + set 0xffff, %o4 + and %o4, %o2, %o0 + sll %o0, 15, %o0 + srl %o3, 17, %o3 + or %o3, %o0, %o0 + addcc %o0, %o1, %o0 + bneg 1f + sethi %hi(0x7fffffff), %o1 + retl +#ifdef PIC + st %o0, [%g1] +#else + st %o0, [%g1 + %lo(randseed)] +#endif +1: + or %o1, %lo(0x7fffffff), %o1 + add %o0, 1, %o0 + and %o1, %o0, %o0 + retl +#ifdef PIC + st %o0, [%g1] +#else + st %o0, [%g1 + %lo(randseed)] +#endif diff --git a/sys/lib/libkern/arch/usermode/Makefile.inc b/sys/lib/libkern/arch/usermode/Makefile.inc new file mode 100644 index 000000000..26c03168b --- /dev/null +++ b/sys/lib/libkern/arch/usermode/Makefile.inc @@ -0,0 +1,6 @@ +# $NetBSD: Makefile.inc,v 1.3 2009/08/14 19:23:55 dsl Exp $ +# +# There are likely more that we will notice when we go native + +NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c +NO_SRCS+= __main.c strlen.c strcmp.c diff --git a/sys/lib/libkern/arch/vax/Makefile.inc b/sys/lib/libkern/arch/vax/Makefile.inc new file mode 100644 index 000000000..18e9abc74 --- /dev/null +++ b/sys/lib/libkern/arch/vax/Makefile.inc @@ -0,0 +1,11 @@ +# $NetBSD: Makefile.inc,v 1.24 2010/03/15 11:46:49 uwe Exp $ +# +# The rest of the lib routines are in machine/macros.h +# + +SRCS+= blkcpy.S blkset.S bswap16.S bswap32.S bswap64.S +SRCS+= random.S +SRCS+= udiv.S urem.S + +NO_SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c +NO_SRCS+= scanc.c skpc.c diff --git a/sys/lib/libkern/arch/vax/blkcpy.S b/sys/lib/libkern/arch/vax/blkcpy.S new file mode 100644 index 000000000..c85518a54 --- /dev/null +++ b/sys/lib/libkern/arch/vax/blkcpy.S @@ -0,0 +1,70 @@ +/* $NetBSD: blkcpy.S,v 1.4 2005/12/11 12:24:45 christos Exp $ */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include + +/* __blkcpy(from, to, size) */ + +ENTRY(__blkcpy, R6) + movl 4(%ap),%r1 + movl 8(%ap),%r3 + movl 12(%ap),%r6 + cmpl %r1,%r3 + bgtr 2f # normal forward case + blss 3f # overlapping, must do backwards + ret # equal, nothing to do +1: + subl2 %r0,%r6 + movc3 %r0,(%r1),(%r3) +2: + movzwl $65535,%r0 + cmpl %r6,%r0 + jgtr 1b + movc3 %r6,(%r1),(%r3) + ret +3: + addl2 %r6,%r1 + addl2 %r6,%r3 + movzwl $65535,%r0 + jbr 5f +4: + subl2 %r0,%r6 + subl2 %r0,%r1 + subl2 %r0,%r3 + movc3 %r0,(%r1),(%r3) + movzwl $65535,%r0 + subl2 %r0,%r1 + subl2 %r0,%r3 +5: + cmpl %r6,%r0 + jgtr 4b + subl2 %r6,%r1 + subl2 %r6,%r3 + movc3 %r6,(%r1),(%r3) + ret diff --git a/sys/lib/libkern/arch/vax/blkset.S b/sys/lib/libkern/arch/vax/blkset.S new file mode 100644 index 000000000..6c34b7f93 --- /dev/null +++ b/sys/lib/libkern/arch/vax/blkset.S @@ -0,0 +1,49 @@ +/* $NetBSD: blkset.S,v 1.5 2005/12/11 12:24:45 christos Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed at Ludd, University of Lule}. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/* + * Set a block of memory larger than 64K. + */ +ENTRY(__blkset,R6|R7) + movl 4(%ap), %r3 + movl 8(%ap), %r7 + movl 12(%ap), %r6 + jbr 2f +1: subl2 %r0, %r6 + movc5 $0,(%r3),%r7,%r0,(%r3) +2: movzwl $65535,%r0 + cmpl %r6, %r0 + jgtr 1b + movc5 $0,(%r3),%r7,%r6,(%r3) + ret diff --git a/sys/lib/libkern/arch/vax/random.S b/sys/lib/libkern/arch/vax/random.S new file mode 100644 index 000000000..b1d9e81e1 --- /dev/null +++ b/sys/lib/libkern/arch/vax/random.S @@ -0,0 +1,104 @@ +/* $NetBSD: random.S,v 1.4 2007/01/14 13:26:18 ragge Exp $ */ + +/* + * Copyright (c) 1994 Ludd, University of Lule}, Sweden. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ + +#include + + .data +randseed: + .long 1 + +ENTRY(random, 0) + movl $16807,%r0 + + movl randseed,%r1 # %r2=16807*loword(randseed) + bicl3 $0xffff0000,%r1,%r2 + mull2 %r0,%r2 + ashl $-16,%r1,%r1 # %r1=16807*hiword(randseed) + bicl2 $0xffff0000,%r1 + mull2 %r0,%r1 + bicl3 $0xffff0000,%r2,%r0 + ashl $-16,%r2,%r2 # %r1+=(%r2>>16) + bicl2 $0xffff0000,%r2 + addl2 %r2,%r1 + ashl $16,%r1,%r2 # %r0|=%r1<<16 + bisl2 %r2,%r0 + ashl $-16,%r1,%r1 # %r1=%r1>>16 + + ashl $1,%r1,%r1 + movl %r0,%r2 + rotl $1,%r0,%r0 + bicl2 $0xfffffffe,%r0 + bisl2 %r0,%r1 + movl %r2,%r0 + bicl2 $0x80000000,%r0 + addl2 %r1,%r0 + bgeq L1 + subl2 $0x7fffffff,%r0 +L1: movl %r0,randseed + ret diff --git a/sys/lib/libkern/arch/x86_64/Makefile.inc b/sys/lib/libkern/arch/x86_64/Makefile.inc new file mode 100644 index 000000000..7a18707a6 --- /dev/null +++ b/sys/lib/libkern/arch/x86_64/Makefile.inc @@ -0,0 +1,10 @@ +# $NetBSD: Makefile.inc,v 1.6 2010/01/14 02:09:46 joerg Exp $ + +SRCS+= byte_swap_2.S byte_swap_4.S byte_swap_8.S +SRCS+= ffs.S +SRCS+= memchr.S memcmp.S memcpy.S memmove.S memset.S +SRCS+= strcat.S strchr.S strcmp.S +SRCS+= strcpy.S strlen.S +SRCS+= strrchr.S +SRCS+= scanc.S skpc.S +SRCS+= random.S diff --git a/sys/lib/libkern/arch/x86_64/random.S b/sys/lib/libkern/arch/x86_64/random.S new file mode 100644 index 000000000..cd179e349 --- /dev/null +++ b/sys/lib/libkern/arch/x86_64/random.S @@ -0,0 +1,90 @@ +/* $NetBSD: random.S,v 1.2 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1990,1993 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Here is a very good random number generator. This implementation is + * based on ``Two Fast Implementations of the "Minimal Standard" Random + * Number Generator'', David G. Carta, Communications of the ACM, Jan 1990, + * Vol 33 No 1. Do NOT modify this code unless you have a very thorough + * understanding of the algorithm. It's trickier than you think. If + * you do change it, make sure that its 10,000'th invocation returns + * 1043618065. + * + * Here is easier-to-decipher pseudocode: + * + * p = (16807*seed)<30:0> # e.g., the low 31 bits of the product + * q = (16807*seed)<62:31> # e.g., the high 31 bits starting at bit 32 + * if (p + q < 2^31) + * seed = p + q + * else + * seed = ((p + q) & (2^31 - 1)) + 1 + * return (seed); + * + * The result is in (0,2^31), e.g., it's always positive. + */ +#include + + .data +randseed: + .long 1 + .text +ENTRY(random) + movl $16807,%eax + imull randseed(%rip) + shld $1,%eax,%edx + andl $0x7fffffff,%eax + addl %edx,%eax + js 1f + movl %eax,randseed(%rip) + ret +1: + subl $0x7fffffff,%eax + movl %eax,randseed(%rip) + ret diff --git a/sys/lib/libkern/arch/x86_64/scanc.S b/sys/lib/libkern/arch/x86_64/scanc.S new file mode 100644 index 000000000..93f4e1254 --- /dev/null +++ b/sys/lib/libkern/arch/x86_64/scanc.S @@ -0,0 +1,55 @@ +/* $NetBSD: scanc.S,v 1.2 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Adapted for NetBSD/x86_64 by Frank van der Linden + */ + +#include + +ENTRY(scanc) + movq %rdx,%r11 + movb %cl,%dl + movl %edi,%ecx + testl %ecx,%ecx + jz 2f + movq %r11,%rdi + xorq %rax,%rax + cld +1: + lodsb + testb %dl,(%rax,%rdi) + jnz 2f + decl %ecx + jnz 1b +2: + movl %ecx,%eax + ret diff --git a/sys/lib/libkern/arch/x86_64/skpc.S b/sys/lib/libkern/arch/x86_64/skpc.S new file mode 100644 index 000000000..d183b7f36 --- /dev/null +++ b/sys/lib/libkern/arch/x86_64/skpc.S @@ -0,0 +1,49 @@ +/* $NetBSD: skpc.S,v 1.2 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Adapted for NetBSD/x86_64 by Frank van der Linden + */ + +#include + +ENTRY(skpc) + movl %edi,%eax + movq %rsi,%rcx + movq %rdx,%rdi + cld + repe + scasb + je 1f + incq %rcx +1: + movl %ecx,%eax + ret diff --git a/sys/lib/libkern/bcd.c b/sys/lib/libkern/bcd.c new file mode 100644 index 000000000..ced51c743 --- /dev/null +++ b/sys/lib/libkern/bcd.c @@ -0,0 +1,25 @@ +/* $NetBSD: bcd.c,v 1.1 2006/03/11 15:40:07 kleink Exp $ */ + +/* + * Convert a single byte between (unsigned) packed bcd and binary. + * Public domain. + */ + +#include +__KERNEL_RCSID(0,"$NetBSD: bcd.c,v 1.1 2006/03/11 15:40:07 kleink Exp $"); + +#include + +unsigned int +bcdtobin(unsigned int bcd) +{ + + return (((bcd >> 4) & 0x0f) * 10 + (bcd & 0x0f)); +} + +unsigned int +bintobcd(unsigned int bin) +{ + + return ((((bin / 10) << 4) & 0xf0) | (bin % 10)); +} diff --git a/sys/lib/libkern/crc32.c b/sys/lib/libkern/crc32.c new file mode 100644 index 000000000..490b6fc5f --- /dev/null +++ b/sys/lib/libkern/crc32.c @@ -0,0 +1,116 @@ +/* $NetBSD: crc32.c,v 1.4 2009/03/26 22:18:14 he Exp $ */ + +/* crc32.c -- compute the CRC-32 of a data stream + * + * Adapted from zlib's crc code. + * + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown 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 +#include + +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 +#include "crc32.h" + +#if BYTE_ORDER == LITTLE_ENDIAN +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len) +{ + register u4 c; + register const u4 *buf4; + + if (buf == NULL) return 0UL; + + c = (u4)crc; + c = ~c; + while (len && ((uintptr_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 *)(const void *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (uint32_t)c; +} + +#else /* BIG_ENDIAN */ + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +uint32_t crc32(uint32_t crc, const uint8_t *buf, size_t len) +{ + register u4 c; + register const u4 *buf4; + + if (buf == NULL) return 0UL; + + c = REV((u4)crc); + c = ~c; + while (len && ((uintptr_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 *)(const void *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (uint32_t)(REV(c)); +} +#endif diff --git a/sys/lib/libkern/crc32.h b/sys/lib/libkern/crc32.h new file mode 100644 index 000000000..22c2f1b64 --- /dev/null +++ b/sys/lib/libkern/crc32.h @@ -0,0 +1,441 @@ +/* $NetBSD: crc32.h,v 1.1 2009/03/25 01:26:13 darran Exp $ */ + +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +static const uint32_t crc_table[8][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL + } +}; diff --git a/sys/lib/libkern/imax.c b/sys/lib/libkern/imax.c new file mode 100644 index 000000000..911bfd4df --- /dev/null +++ b/sys/lib/libkern/imax.c @@ -0,0 +1,41 @@ +/* $NetBSD: imax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +int +imax(int a, int b) +{ + return (a > b ? a : b); +} diff --git a/sys/lib/libkern/imin.c b/sys/lib/libkern/imin.c new file mode 100644 index 000000000..0e73f38c5 --- /dev/null +++ b/sys/lib/libkern/imin.c @@ -0,0 +1,41 @@ +/* $NetBSD: imin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +int +imin(int a, int b) +{ + return (a < b ? a : b); +} diff --git a/sys/lib/libkern/intoa.c b/sys/lib/libkern/intoa.c new file mode 100644 index 000000000..2f781b1e8 --- /dev/null +++ b/sys/lib/libkern/intoa.c @@ -0,0 +1,79 @@ +/* $NetBSD: intoa.c,v 1.3 2009/03/14 15:36:22 dsl Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include + +#if defined(_KERNEL) || defined(_STANDALONE) +#include +#else +char *intoa(u_int32_t); /* XXX */ +#endif + +/* Similar to inet_ntoa() */ +char * +intoa(u_int32_t addr) +{ + char *cp; + u_int byte; + int n; + static char buf[17]; /* strlen(".255.255.255.255") + 1 */ + + addr = ntohl(addr); + cp = &buf[sizeof buf]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + return (cp+1); +} diff --git a/sys/lib/libkern/kern_assert.c b/sys/lib/libkern/kern_assert.c new file mode 100644 index 000000000..5880a7d82 --- /dev/null +++ b/sys/lib/libkern/kern_assert.c @@ -0,0 +1,52 @@ +/* $NetBSD: kern_assert.c,v 1.2 2011/09/29 20:50:09 christos Exp $ */ + +/* + * Copyright (c) 1996 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#ifdef _STANDALONE +#include +#endif + +void +kern_assert(const char *fmt, ...) +{ + va_list ap; +#ifdef _KERNEL + if (panicstr != NULL) + return; +#endif + va_start(ap, fmt); + vpanic(fmt, ap); + va_end(ap); +} diff --git a/sys/lib/libkern/libkern.h b/sys/lib/libkern/libkern.h new file mode 100644 index 000000000..e6fc8b886 --- /dev/null +++ b/sys/lib/libkern/libkern.h @@ -0,0 +1,346 @@ +/* $NetBSD: libkern.h,v 1.104 2011/11/28 08:05:06 tls Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)libkern.h 8.2 (Berkeley) 8/5/94 + */ + +#ifndef _LIB_LIBKERN_LIBKERN_H_ +#define _LIB_LIBKERN_LIBKERN_H_ + +#include +#include +#include + +#ifndef LIBKERN_INLINE +#define LIBKERN_INLINE static __inline +#define LIBKERN_BODY +#endif + +LIBKERN_INLINE int imax(int, int) __unused; +LIBKERN_INLINE int imin(int, int) __unused; +LIBKERN_INLINE u_int max(u_int, u_int) __unused; +LIBKERN_INLINE u_int min(u_int, u_int) __unused; +LIBKERN_INLINE long lmax(long, long) __unused; +LIBKERN_INLINE long lmin(long, long) __unused; +LIBKERN_INLINE u_long ulmax(u_long, u_long) __unused; +LIBKERN_INLINE u_long ulmin(u_long, u_long) __unused; +LIBKERN_INLINE int abs(int) __unused; + +LIBKERN_INLINE int isspace(int) __unused; +LIBKERN_INLINE int isascii(int) __unused; +LIBKERN_INLINE int isupper(int) __unused; +LIBKERN_INLINE int islower(int) __unused; +LIBKERN_INLINE int isalpha(int) __unused; +LIBKERN_INLINE int isdigit(int) __unused; +LIBKERN_INLINE int isxdigit(int) __unused; +LIBKERN_INLINE int toupper(int) __unused; +LIBKERN_INLINE int tolower(int) __unused; + +#ifdef LIBKERN_BODY +LIBKERN_INLINE int +imax(int a, int b) +{ + return (a > b ? a : b); +} +LIBKERN_INLINE int +imin(int a, int b) +{ + return (a < b ? a : b); +} +LIBKERN_INLINE long +lmax(long a, long b) +{ + return (a > b ? a : b); +} +LIBKERN_INLINE long +lmin(long a, long b) +{ + return (a < b ? a : b); +} +LIBKERN_INLINE u_int +max(u_int a, u_int b) +{ + return (a > b ? a : b); +} +LIBKERN_INLINE u_int +min(u_int a, u_int b) +{ + return (a < b ? a : b); +} +LIBKERN_INLINE u_long +ulmax(u_long a, u_long b) +{ + return (a > b ? a : b); +} +LIBKERN_INLINE u_long +ulmin(u_long a, u_long b) +{ + return (a < b ? a : b); +} + +LIBKERN_INLINE int +abs(int j) +{ + return(j < 0 ? -j : j); +} + +LIBKERN_INLINE int +isspace(int ch) +{ + return (ch == ' ' || (ch >= '\t' && ch <= '\r')); +} + +LIBKERN_INLINE int +isascii(int ch) +{ + return ((ch & ~0x7f) == 0); +} + +LIBKERN_INLINE int +isupper(int ch) +{ + return (ch >= 'A' && ch <= 'Z'); +} + +LIBKERN_INLINE int +islower(int ch) +{ + return (ch >= 'a' && ch <= 'z'); +} + +LIBKERN_INLINE int +isalpha(int ch) +{ + return (isupper(ch) || islower(ch)); +} + +LIBKERN_INLINE int +isdigit(int ch) +{ + return (ch >= '0' && ch <= '9'); +} + +LIBKERN_INLINE int +isxdigit(int ch) +{ + return (isdigit(ch) || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f')); +} + +LIBKERN_INLINE int +toupper(int ch) +{ + if (islower(ch)) + return (ch - 0x20); + return (ch); +} + +LIBKERN_INLINE int +tolower(int ch) +{ + if (isupper(ch)) + return (ch + 0x20); + return (ch); +} +#endif + +#define __NULL_STMT do { } while (/* CONSTCOND */ 0) + +#define __KASSERTSTR "kernel %sassertion \"%s\" failed: file \"%s\", line %d " + +#ifdef NDEBUG /* tradition! */ +#define assert(e) ((void)0) +#else +#define assert(e) (__predict_true((e)) ? (void)0 : \ + kern_assert(__KASSERTSTR, "", #e, __FILE__, __LINE__)) +#endif + +#ifdef __COVERITY__ +#ifndef DIAGNOSTIC +#define DIAGNOSTIC +#endif +#endif + +#define CTASSERT(x) __CTASSERT(x) + +#ifndef DIAGNOSTIC +#define _DIAGASSERT(a) (void)0 +#ifdef lint +#define KASSERTMSG(e, msg, ...) /* NOTHING */ +#define KASSERT(e) /* NOTHING */ +#else /* !lint */ +#define KASSERTMSG(e, msg, ...) ((void)0) +#define KASSERT(e) ((void)0) +#endif /* !lint */ +#else /* DIAGNOSTIC */ +#define _DIAGASSERT(a) assert(a) +#define KASSERTMSG(e, msg, ...) \ + (__predict_true((e)) ? (void)0 : \ + kern_assert(__KASSERTSTR msg, "diagnostic ", #e, \ + __FILE__, __LINE__, ## __VA_ARGS__)) + +#define KASSERT(e) (__predict_true((e)) ? (void)0 : \ + kern_assert(__KASSERTSTR, "diagnostic ", #e, \ + __FILE__, __LINE__)) +#endif + +#ifndef DEBUG +#ifdef lint +#define KDASSERTMSG(e,msg, ...) /* NOTHING */ +#define KDASSERT(e) /* NOTHING */ +#else /* lint */ +#define KDASSERTMSG(e,msg, ...) ((void)0) +#define KDASSERT(e) ((void)0) +#endif /* lint */ +#else +#define KDASSERTMSG(e, msg, ...) \ + (__predict_true((e)) ? (void)0 : \ + kern_assert(__KASSERTSTR msg, "debugging ", #e, \ + __FILE__, __LINE__, ## __VA_ARGS__)) + +#define KDASSERT(e) (__predict_true((e)) ? (void)0 : \ + kern_assert(__KASSERTSTR, "debugging ", #e, \ + __FILE__, __LINE__)) +#endif + +/* + * XXX: For compatibility we use SMALL_RANDOM by default. + */ +#define SMALL_RANDOM + +#ifndef offsetof +#if __GNUC_PREREQ__(4, 0) +#define offsetof(type, member) __builtin_offsetof(type, member) +#else +#define offsetof(type, member) \ + ((size_t)(unsigned long)(&(((type *)0)->member))) +#endif +#endif + +#define MTPRNG_RLEN 624 +struct mtprng_state { + unsigned int mt_idx; + uint32_t mt_elem[MTPRNG_RLEN]; + uint32_t mt_count; + uint32_t mt_sparse[3]; +}; + +/* Prototypes for which GCC built-ins exist. */ +void *memcpy(void *, const void *, size_t); +int memcmp(const void *, const void *, size_t); +void *memset(void *, int, size_t); +#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE) +#define memcpy(d, s, l) __builtin_memcpy(d, s, l) +#define memcmp(a, b, l) __builtin_memcmp(a, b, l) +#endif +#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE) +#define memset(d, v, l) __builtin_memset(d, v, l) +#endif + +char *strcpy(char *, const char *); +int strcmp(const char *, const char *); +size_t strlen(const char *); +size_t strnlen(const char *, size_t); +char *strsep(char **, const char *); +#if __GNUC_PREREQ__(2, 95) && !defined(_STANDALONE) +#define strcpy(d, s) __builtin_strcpy(d, s) +#define strcmp(a, b) __builtin_strcmp(a, b) +#define strlen(a) __builtin_strlen(a) +#endif + +/* Functions for which we always use built-ins. */ +#ifdef __GNUC__ +#define alloca(s) __builtin_alloca(s) +#endif + +/* These exist in GCC 3.x, but we don't bother. */ +char *strcat(char *, const char *); +char *strncpy(char *, const char *, size_t); +int strncmp(const char *, const char *, size_t); +char *strchr(const char *, int); +char *strrchr(const char *, int); + +char *strstr(const char *, const char *); + +/* + * ffs is an instruction on vax. + */ +int ffs(int); +#if __GNUC_PREREQ__(2, 95) && (!defined(__vax__) || __GNUC_PREREQ__(4,1)) +#define ffs(x) __builtin_ffs(x) +#endif + +void kern_assert(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +unsigned int + bcdtobin(unsigned int); +unsigned int + bintobcd(unsigned int); +u_int32_t + inet_addr(const char *); +struct in_addr; +int inet_aton(const char *, struct in_addr *); +char *intoa(u_int32_t); +#define inet_ntoa(a) intoa((a).s_addr) +void *memchr(const void *, int, size_t); +void *memmove(void *, const void *, size_t); +int pmatch(const char *, const char *, const char **); +#ifndef SMALL_RANDOM +void srandom(unsigned long); +char *initstate(unsigned long, char *, size_t); +char *setstate(char *); +#endif /* SMALL_RANDOM */ +long random(void); +void mtprng_init32(struct mtprng_state *, uint32_t); +void mtprng_initarray(struct mtprng_state *, const uint32_t *, size_t); +uint32_t mtprng_rawrandom(struct mtprng_state *); +uint32_t mtprng_random(struct mtprng_state *); +int scanc(u_int, const u_char *, const u_char *, int); +int skpc(int, size_t, u_char *); +int strcasecmp(const char *, const char *); +size_t strlcpy(char *, const char *, size_t); +size_t strlcat(char *, const char *, size_t); +int strncasecmp(const char *, const char *, size_t); +u_long strtoul(const char *, char **, int); +long long strtoll(const char *, char **, int); +unsigned long long strtoull(const char *, char **, int); +uintmax_t strtoumax(const char *, char **, int); +int snprintb(char *, size_t, const char *, uint64_t); +int snprintb_m(char *, size_t, const char *, uint64_t, size_t); +int kheapsort(void *, size_t, size_t, int (*)(const void *, const void *), + void *); +uint32_t crc32(uint32_t, const uint8_t *, size_t); +unsigned int popcount(unsigned int) __constfunc; +unsigned int popcountl(unsigned long) __constfunc; +unsigned int popcountll(unsigned long long) __constfunc; +unsigned int popcount32(uint32_t) __constfunc; +unsigned int popcount64(uint64_t) __constfunc; +#endif /* !_LIB_LIBKERN_LIBKERN_H_ */ diff --git a/sys/lib/libkern/lmax.c b/sys/lib/libkern/lmax.c new file mode 100644 index 000000000..cabb7b19a --- /dev/null +++ b/sys/lib/libkern/lmax.c @@ -0,0 +1,41 @@ +/* $NetBSD: lmax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +long +lmax(long a, long b) +{ + return (a > b ? a : b); +} diff --git a/sys/lib/libkern/lmin.c b/sys/lib/libkern/lmin.c new file mode 100644 index 000000000..ef49b7773 --- /dev/null +++ b/sys/lib/libkern/lmin.c @@ -0,0 +1,41 @@ +/* $NetBSD: lmin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +long +lmin(long a, long b) +{ + return (a < b ? a : b); +} diff --git a/sys/lib/libkern/max.c b/sys/lib/libkern/max.c new file mode 100644 index 000000000..eae7bdc23 --- /dev/null +++ b/sys/lib/libkern/max.c @@ -0,0 +1,41 @@ +/* $NetBSD: max.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +unsigned int +max(unsigned int a, unsigned int b) +{ + return (a > b ? a : b); +} diff --git a/sys/lib/libkern/mertwist.c b/sys/lib/libkern/mertwist.c new file mode 100644 index 000000000..3613449d4 --- /dev/null +++ b/sys/lib/libkern/mertwist.c @@ -0,0 +1,222 @@ +/* $NetBSD: mertwist.c,v 1.8 2008/04/28 20:24:06 martin Exp $ */ +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas . + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 +#include +#include + +#include +#else +#include +#include +#include +#include +#define KASSERT(x) assert(x) +#endif + +/* + * Mersenne Twister. Produces identical output compared to mt19937ar.c + * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + */ + +#define MATRIX_A(a) (((a) & 1) ? 0x9908b0df : 0) +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define UPPER_MASK 0x80000000 +#define LOWER_MASK 0x7fffffff +#define MIX(u,l) (((u) & UPPER_MASK) | ((l) & LOWER_MASK)) + +#define KNUTH_MULTIPLIER 0x6c078965 + +#ifndef MTPRNG_RLEN +#define MTPRNG_RLEN 624 +#endif +#define MTPRNG_POS1 397 + +static void mtprng_refresh(struct mtprng_state *); + +/* + * Initialize the generator from a seed + */ +void +mtprng_init32(struct mtprng_state *mt, uint32_t seed) +{ + size_t i; + + /* + * Use Knuth's algorithm for expanding this seed over its + * portion of the key space. + */ + mt->mt_elem[0] = seed; + for (i = 1; i < MTPRNG_RLEN; i++) { + mt->mt_elem[i] = KNUTH_MULTIPLIER + * (mt->mt_elem[i-1] ^ (mt->mt_elem[i-1] >> 30)) + i; + } + + mtprng_refresh(mt); +} + +void +mtprng_initarray(struct mtprng_state *mt, const uint32_t *key, size_t keylen) +{ + uint32_t *mp; + size_t i, j, k; + + /* + * Use Knuth's algorithm for expanding this seed over its + * portion of the key space. + */ + mt->mt_elem[0] = 19650218UL; + for (i = 1; i < MTPRNG_RLEN; i++) { + mt->mt_elem[i] = KNUTH_MULTIPLIER + * (mt->mt_elem[i-1] ^ (mt->mt_elem[i-1] >> 30)) + i; + } + + KASSERT(keylen > 0); + + i = 1; + j = 0; + k = (keylen < MTPRNG_RLEN ? MTPRNG_RLEN : keylen); + + mp = &mt->mt_elem[1]; + for (; k-- > 0; mp++) { + mp[0] ^= (mp[-1] ^ (mp[-1] >> 30)) * 1664525UL; + mp[0] += key[j] + j; + if (++i == MTPRNG_RLEN) { + KASSERT(mp == mt->mt_elem + MTPRNG_RLEN - 1); + mt->mt_elem[0] = mp[0]; + i = 1; + mp = mt->mt_elem; + } + if (++j == keylen) + j = 0; + } + for (j = MTPRNG_RLEN; --j > 0; mp++) { + mp[0] ^= (mp[-1] ^ (mp[-1] >> 30)) * 1566083941UL; + mp[0] -= i; + if (++i == MTPRNG_RLEN) { + KASSERT(mp == mt->mt_elem + MTPRNG_RLEN - 1); + mt->mt_elem[0] = mp[0]; + i = 1; + mp = mt->mt_elem; + } + } + mt->mt_elem[0] = 0x80000000; + mtprng_refresh(mt); +} + +/* + * Generate an array of 624 untempered numbers + */ +void +mtprng_refresh(struct mtprng_state *mt) +{ + uint32_t y; + size_t i, j; + /* + * The following has been refactored to avoid the need for 'mod 624' + */ + for (i = 0, j = MTPRNG_POS1; j < MTPRNG_RLEN; i++, j++) { + y = MIX(mt->mt_elem[i], mt->mt_elem[i+1]); + mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y); + } + for (j = 0; i < MTPRNG_RLEN - 1; i++, j++) { + y = MIX(mt->mt_elem[i], mt->mt_elem[i+1]); + mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y); + } + y = MIX(mt->mt_elem[MTPRNG_RLEN - 1], mt->mt_elem[0]); + mt->mt_elem[MTPRNG_RLEN - 1] = + mt->mt_elem[MTPRNG_POS1 - 1] ^ (y >> 1) ^ MATRIX_A(y); +} + +/* + * Extract a tempered PRN based on the current index. Then recompute a + * new value for the index. This avoids having to regenerate the array + * every 624 iterations. We can do this since recomputing only the next + * element and the [(i + 397) % 624] one. + */ +uint32_t +mtprng_rawrandom(struct mtprng_state *mt) +{ + uint32_t x, y; + const size_t i = mt->mt_idx; + size_t j; + + /* + * First generate the random value for the current position. + */ + x = mt->mt_elem[i]; + x ^= x >> 11; + x ^= (x << 7) & TEMPERING_MASK_B; + x ^= (x << 15) & TEMPERING_MASK_C; + x ^= x >> 18; + + /* + * Next recalculate the next sequence for the current position. + */ + y = mt->mt_elem[i]; + if (__predict_true(i < MTPRNG_RLEN - 1)) { + /* + * Avoid doing % since it can be expensive. + * j = (i + MTPRNG_POS1) % MTPRNG_RLEN; + */ + j = i + MTPRNG_POS1; + if (j >= MTPRNG_RLEN) + j -= MTPRNG_RLEN; + mt->mt_idx++; + } else { + j = MTPRNG_POS1 - 1; + mt->mt_idx = 0; + } + y = MIX(y, mt->mt_elem[mt->mt_idx]); + mt->mt_elem[i] = mt->mt_elem[j] ^ (y >> 1) ^ MATRIX_A(y); + + /* + * Return the value calculated in the first step. + */ + return x; +} + +/* + * This is a non-standard routine which attempts to return a cryptographically + * strong random number by collapsing 2 32bit values outputed by the twister + * into one 32bit value. + */ +uint32_t +mtprng_random(struct mtprng_state *mt) +{ + uint32_t a; + + mt->mt_count = (mt->mt_count + 13) & 31; + a = mtprng_rawrandom(mt); + a = (a << mt->mt_count) | (a >> (32 - mt->mt_count)); + return a + mtprng_rawrandom(mt); +} diff --git a/sys/lib/libkern/milieu.h b/sys/lib/libkern/milieu.h new file mode 100644 index 000000000..863a28cd4 --- /dev/null +++ b/sys/lib/libkern/milieu.h @@ -0,0 +1,147 @@ +/* $NetBSD: milieu.h,v 1.3 2008/04/28 20:24:06 martin Exp $ */ + +/* This is a derivative work. */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ross Harvey. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#ifndef MILIEU_H +#define MILIEU_H + +#if !defined(_KERNEL) && !defined(_STANDALONE) +#include +#else +#include +#endif + +#include + +/* +------------------------------------------------------------------------------- +One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. +------------------------------------------------------------------------------- +*/ + +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define LITTLEENDIAN +#else +#define BIGENDIAN +#endif + +#define BITS64 + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines the most convenient type that holds +integers of at least as many bits as specified. For example, `uint8' should +be the most convenient type that can hold unsigned integers of as many as +8 bits. The `flag' type must be able to hold either a 0 or 1. For most +implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed +to the same as `int'. +------------------------------------------------------------------------------- +*/ +typedef int flag; +typedef unsigned int uint8; +typedef signed int int8; +typedef unsigned int uint16; +typedef int int16; +typedef unsigned int uint32; +typedef signed int int32; +#ifdef BITS64 +typedef uint64_t uint64; +typedef int64_t int64; +#endif + +/* +------------------------------------------------------------------------------- +Each of the following `typedef's defines a type that holds integers +of _exactly_ the number of bits specified. For instance, for most +implementation of C, `bits16' and `sbits16' should be `typedef'ed to +`unsigned short int' and `signed short int' (or `short int'), respectively. +------------------------------------------------------------------------------- +*/ +typedef uint8_t bits8; +typedef int8_t sbits8; +typedef uint16_t bits16; +typedef int16_t sbits16; +typedef uint32_t bits32; +typedef int32_t sbits32; +#ifdef BITS64 +typedef uint64_t bits64; +typedef int64_t sbits64; +#endif + +#ifdef BITS64 +/* +------------------------------------------------------------------------------- +The `LIT64' macro takes as its argument a textual integer literal and +if necessary ``marks'' the literal as having a 64-bit integer type. +For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +appended with the letters `LL' standing for `long long', which is `gcc's +name for the 64-bit integer type. Some compilers may allow `LIT64' to be +defined as the identity macro: `#define LIT64( a ) a'. +------------------------------------------------------------------------------- +*/ +#define LIT64( a ) a##LL +#endif + +/* +------------------------------------------------------------------------------- +The macro `INLINE' can be used before functions that should be inlined. If +a compiler does not support explicit inlining, this macro should be defined +to be `static'. +------------------------------------------------------------------------------- +*/ +#define INLINE static inline + +#endif diff --git a/sys/lib/libkern/min.c b/sys/lib/libkern/min.c new file mode 100644 index 000000000..935c06db8 --- /dev/null +++ b/sys/lib/libkern/min.c @@ -0,0 +1,41 @@ +/* $NetBSD: min.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +unsigned int +min(unsigned int a, unsigned int b) +{ + return (a < b ? a : b); +} diff --git a/sys/lib/libkern/pmatch.c b/sys/lib/libkern/pmatch.c new file mode 100644 index 000000000..fe7f61904 --- /dev/null +++ b/sys/lib/libkern/pmatch.c @@ -0,0 +1,130 @@ +/* $NetBSD: pmatch.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +/* + * pmatch(): + * Return 2 on exact match. + * Return 1 on substring match. + * Return 0 on no match. + * Return -1 on error. + * *estr will point to the end of thelongest exact or substring match. + */ +int +pmatch(const char *string, const char *pattern, const char **estr) +{ + u_char stringc, patternc, rangec; + int match, negate_range; + const char *oestr, *pestr, *testr; + + if (estr == NULL) + estr = &testr; + + for (;; ++string) { + stringc = *string; + switch (patternc = *pattern++) { + case 0: + *estr = string; + return stringc == '\0' ? 2 : 1; + case '?': + if (stringc == '\0') + return 0; + *estr = string; + break; + case '*': + if (!*pattern) { + while (*string) + string++; + *estr = string; + return 2; + } + oestr = *estr; + pestr = NULL; + + do { + switch (pmatch(string, pattern, estr)) { + case -1: + return -1; + case 0: + break; + case 1: + pestr = *estr; + break; + case 2: + return 2; + default: + return -1; + } + *estr = string; + } + while (*string++); + + if (pestr) { + *estr = pestr; + return 1; + } else { + *estr = oestr; + return 0; + } + + case '[': + match = 0; + if ((negate_range = (*pattern == '^')) != 0) + pattern++; + while ((rangec = *pattern++) != '\0') { + if (rangec == ']') + break; + if (match) + continue; + if (rangec == '-' && *(pattern - 2) != '[' && + *pattern != ']') { + match = + stringc <= (u_char)*pattern && + (u_char)*(pattern - 2) <= stringc; + pattern++; + } else + match = (stringc == rangec); + } + if (rangec == 0) + return -1; + if (match == negate_range) + return 0; + *estr = string; + break; + default: + if (patternc != stringc) + return 0; + *estr = string; + break; + } + } +} diff --git a/sys/lib/libkern/rngtest.c b/sys/lib/libkern/rngtest.c new file mode 100644 index 000000000..c20263e4d --- /dev/null +++ b/sys/lib/libkern/rngtest.c @@ -0,0 +1,281 @@ +/* $NetBSD: rngtest.c,v 1.2 2011/11/25 12:45:00 joerg Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Thor Lancelot Simon. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* fips140.c 1.5 (Qualcomm) 02/09/02 */ +/* +This software is free for commercial and non-commercial use +subject to the following conditions. + +Copyright remains vested in QUALCOMM Incorporated, and Copyright +notices in the code are not to be removed. If this package is used in +a product, QUALCOMM should be given attribution as the author this +software. This can be in the form of a textual message at program +startup or in documentation (online or textual) provided with the +package. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +3. All advertising materials mentioning features or use of this + software must display the following acknowledgement: This product + includes software developed by QUALCOMM Incorporated. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +The license and distribution terms for any publically available version +or derivative of this code cannot be changed, that is, this code cannot +simply be copied and put under another distribution license including +the GNU Public License. +*/ + +/* Run FIPS 140 statistical tests on a file */ + +/* written by Greg Rose, Copyright C 2000 QUALCOMM Incorporated */ + +/* + * Modified for in-kernel use (API adjustments, conversion from + * floating to fixed-point chi-sq computation) by Thor Lancelot + * Simon. + * + * A comment on appropriate use of this test and the infamous FIPS 140 + * "continuous output test" (COT): Both tests are very appropriate for + * software interfaces to hardware implementations, and will quickly tell + * you if any number of very bad things have happened to your RNG: perhaps + * it has come disconnected from the rest of the system, somehow, and you + * are getting only unconditioned bus noise (read: clock edges from the + * loudest thing in your system). Perhaps it has ceased to latch a shift + * register and is feeding you the same data over and over again. Perhaps + * it is not really random at all but was sold to you as such. Perhaps it + * is not actually *there* (Intel chipset RNG anyone?) but claims to be, + * and is feeding you 01010101 on every register read. + * + * However, when applied to software RNGs, the situation is quite different. + * Most software RNGs use a modern hash function or cipher as an output + * stage. The resulting bitstream assuredly *should* pass both the + * "continuous output" (no two consecutive samples identical) and + * statistical tests: if it does not, the cryptographic primitive or its + * implementation is terribly broken. + * + * There is still value to this test: it will tell you if you inadvertently + * terribly break your implementation of the software RNG. Which is a thing + * that has in fact happened from time to time, even to the careful (or + * paranoid). But it will not tell you if there is a problem with the + * _input_ to that final cryptographic primitive -- the bits that are hashed + * or the key to the cipher -- and if an adversary can find one, you're + * still toast. + * + * The situation is -- sadly -- similar with hardware RNGs that are + * certified to one of the standards such as X9.31 or SP800-90. In these + * cases the hardware vendor has hidden the actual random bitstream behind + * a hardware cipher/hash implementation that should, indeed, produce good + * quality random numbers that pass will pass this test -- whether the + * underlying bitstream is trustworthy or not. + * + * However, this test (and the COT) will still probably tell you if the + * thing fell off the bus, etc. Which is a thing that has in fact + * happened from time to time, even to the fully certified... + * + * This module does not (yet?) implement the Continuous Output Test. When + * I call that test "infamous", it's because it obviously reduces the + * backtracking resistance of any implementation that includes it -- the + * implementation has to store the entire previous RNG output in order to + * perform the required comparison; not just periodically but all the time + * when operating at all. Nonetheless, it has obvious value for + * hardware implementations where it will quickly and surely detect a + * severe failure; but as of this writing several of the latest comments + * on SP800-90 recommend removing any requirement for the COT and my + * personal tendency is to agree. It's easy to add if you really need it. + * + */ + +#include +#include +#include + +#include + +#include +__KERNEL_RCSID(0, "$NetBSD: rngtest.c,v 1.2 2011/11/25 12:45:00 joerg Exp $"); + +#ifndef _KERNEL +static inline int +printf(const char * __restrict format, ...) +{ + return 0; /* XXX no standard way to do output in libkern? */ +} +#endif + +int bitnum = 0; + +const int minrun[7] = {0, 2315, 1114, 527, 240, 103, 103}; +const int maxrun[7] = {0, 2685, 1386, 723, 384, 209, 209}; +#define LONGRUN 26 +#define MINONES 9725 +#define MAXONES 10275 +#define MINPOKE 2.16 +#define MAXPOKE 46.17 +#define PRECISION 100000 + +const int longrun = LONGRUN; +const int minones = MINONES; +const int maxones = MAXONES; +const long long minpoke = (MINPOKE * PRECISION); +const long long maxpoke = (MAXPOKE * PRECISION); + +/* Population count of 1's in a byte */ +const unsigned char Popcount[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + +/* end of run */ +static void +endrun(rngtest_t *const rc, const int last, int run) +{ + if (run >= longrun) { + printf("Kernel RNG \"%s\" long run test FAILURE: " + "Run of %d %ds found\n", rc->rt_name, run, last); + ++rc->rt_nerrs; + } + if (run > 6) + run = 6; + ++rc->rt_runs[last][run]; +} + +int +rngtest(rngtest_t *const rc) +{ + int i; + uint8_t *p; + int c; + long long X; + int last; + int run; + + /* Enforce sanity for most members of the context */ + memset(rc->rt_poker, 0, sizeof(rc->rt_poker)); + memset(rc->rt_runs, 0, sizeof(rc->rt_runs)); + rc->rt_nerrs = 0; + rc->rt_name[sizeof(rc->rt_name) - 1] = '\0'; + + /* monobit test */ + for (p = rc->rt_b, c = 0; p < &rc->rt_b[sizeof rc->rt_b]; ++p) + c += Popcount[*p]; + if (c <= minones || maxones <= c) { + printf("Kernel RNG \"%s\" monobit test FAILURE: %d ones\n", + rc->rt_name, c); + ++rc->rt_nerrs; + } + /* poker test */ + for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) { + ++rc->rt_poker[*p & 0xF]; + ++rc->rt_poker[(*p >> 4) & 0xF]; + } + for (X = i = 0; i < 16; ++i) { + X += rc->rt_poker[i] * rc->rt_poker[i]; + } + X *= PRECISION; + X = 16 * X / 5000 - 5000 * PRECISION; + if (X <= minpoke || maxpoke <= X) { + printf("Kernel RNG \"%s\" poker test failure: " + "parameter X = %lld.%lld\n", rc->rt_name, + (X / PRECISION), (X % PRECISION)); + ++rc->rt_nerrs; + } + /* runs test */ + last = (rc->rt_b[0] >> 7) & 1; + run = 0; + for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) { + c = *p; + for (i = 7; i >= 0; --i) { + if (((c >> i) & 1) != last) { + endrun(rc, last, run); + run = 0; + last = (c >> i) & 1; + } + ++run; + } + } + endrun(rc, last, run); + + for (run = 1; run <= 6; ++run) { + for (last = 0; last <= 1; ++last) { + if (rc->rt_runs[last][run] <= minrun[run]) { + printf("Kernel RNG \"%s\" runs test FAILURE: " + "too few runs of %d %ds (%d < %d)\n", + rc->rt_name, run, last, + rc->rt_runs[last][run], minrun[run]); + ++rc->rt_nerrs; + } else if (rc->rt_runs[last][run] >= maxrun[run]) { + printf("Kernel RNG \"%s\" runs test FAILURE: " + "too many runs of %d %ds (%d > %d)\n", + rc->rt_name, run, last, + rc->rt_runs[last][run], maxrun[run]); + ++rc->rt_nerrs; + } + } + } + memset(rc->rt_b, 0, sizeof(rc->rt_b)); + return rc->rt_nerrs; +} diff --git a/sys/lib/libkern/scanc.c b/sys/lib/libkern/scanc.c new file mode 100644 index 000000000..7c8ebbcba --- /dev/null +++ b/sys/lib/libkern/scanc.c @@ -0,0 +1,45 @@ +/* $NetBSD: scanc.c,v 1.8 2005/12/11 12:24:37 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_subr.c 7.13 (Berkeley) 6/28/90 + */ + +#include +#include + +int +scanc(u_int size, const u_char *cp, const u_char table[], int mask) +{ + const u_char *end = &cp[size]; + + while (cp < end && (table[*cp] & mask) == 0) + cp++; + return (end - cp); +} diff --git a/sys/lib/libkern/skpc.c b/sys/lib/libkern/skpc.c new file mode 100644 index 000000000..36b94ab4a --- /dev/null +++ b/sys/lib/libkern/skpc.c @@ -0,0 +1,45 @@ +/* $NetBSD: skpc.c,v 1.7 2009/03/14 15:36:22 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_subr.c 7.13 (Berkeley) 6/28/90 + */ + +#include +#include + +int +skpc(int mask, size_t size, u_char *cp) +{ + u_char *end = &cp[size]; + + while (cp < end && *cp == (u_char) mask) + cp++; + return (end - cp); +} diff --git a/sys/lib/libkern/softfloat-macros.h b/sys/lib/libkern/softfloat-macros.h new file mode 100644 index 000000000..499a48614 --- /dev/null +++ b/sys/lib/libkern/softfloat-macros.h @@ -0,0 +1,745 @@ +/* $NetBSD: softfloat-macros.h,v 1.1 2001/04/26 03:10:47 ross Exp $ */ + +/* +=============================================================================== + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Shifts `a' right by the number of bits given in `count'. If any nonzero +bits are shifted off, they are ``jammed'' into the least significant bit of +the result by setting the least significant bit to 1. The value of `count' +can be arbitrarily large; in particular, if `count' is greater than 32, the +result will be either 0 or 1, depending on whether `a' is zero or nonzero. +The result is stored in the location pointed to by `zPtr'. +------------------------------------------------------------------------------- +*/ +INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) +{ + bits32 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 32 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/* +------------------------------------------------------------------------------- +Shifts `a' right by the number of bits given in `count'. If any nonzero +bits are shifted off, they are ``jammed'' into the least significant bit of +the result by setting the least significant bit to 1. The value of `count' +can be arbitrarily large; in particular, if `count' is greater than 64, the +result will be either 0 or 1, depending on whether `a' is zero or nonzero. +The result is stored in the location pointed to by `zPtr'. +------------------------------------------------------------------------------- +*/ +INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) +{ + bits64 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 64 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/* +------------------------------------------------------------------------------- +Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 +_plus_ the number of bits given in `count'. The shifted result is at most +64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The +bits shifted off form a second 64-bit result as follows: The _last_ bit +shifted off is the most-significant bit of the extra result, and the other +63 bits of the extra result are all zero if and only if _all_but_the_last_ +bits shifted off were all zero. This extra result is stored in the location +pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. + (This routine makes more sense if `a0' and `a1' are considered to form a +fixed-point value with binary point between `a0' and `a1'. This fixed-point +value is shifted right by the number of bits given in `count', and the +integer part of the result is returned at the location pointed to by +`z0Ptr'. The fractional part of the result may be slightly corrupted as +described above, and is returned at the location pointed to by `z1Ptr'.) +------------------------------------------------------------------------------- +*/ +INLINE void + shift64ExtraRightJamming( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>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<>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<>count ) | ( ( a1<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( a1 != 0 ); + } + else if ( count < 128 ) { + z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); + z0 = a0>>count; + } + else { + if ( count == 64 ) { + z2 = a1; + z1 = a0; + } + else { + a2 |= a1; + if ( count < 128 ) { + z2 = 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 ) & 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<>negCount; + z0 |= a1>>negCount; + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit +value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so +any carry out is lost. The result is broken into two 64-bit pieces which +are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + add128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z1; + + z1 = a1 + b1; + *z1Ptr = z1; + *z0Ptr = a0 + b0 + ( z1 < a1 ); + +} + +/* +------------------------------------------------------------------------------- +Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +modulo 2^192, so any carry out is lost. The result is broken into three +64-bit pieces which are stored at the locations pointed to by `z0Ptr', +`z1Ptr', and `z2Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + add192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 carry0, carry1; + + z2 = a2 + b2; + carry1 = ( z2 < a2 ); + z1 = a1 + b1; + carry0 = ( z1 < a1 ); + z0 = a0 + b0; + z1 += carry1; + z0 += ( z1 < carry1 ); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +2^128, so any borrow out (carry out) is lost. The result is broken into two +64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +`z1Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + sub128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - ( a1 < b1 ); + +} + +/* +------------------------------------------------------------------------------- +Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' +from the 192-bit value formed by concatenating `a0', `a1', and `a2'. +Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The +result is broken into three 64-bit pieces which are stored at the locations +pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + sub192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 borrow0, borrow1; + + z2 = a2 - b2; + borrow1 = ( a2 < b2 ); + z1 = a1 - b1; + borrow0 = ( a1 < b1 ); + z0 = a0 - b0; + z0 -= ( z1 < borrow1 ); + z1 -= borrow1; + z0 -= borrow0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Multiplies `a' by `b' to obtain a 128-bit product. The product is broken +into two 64-bit pieces which are stored at the locations pointed to by +`z0Ptr' and `z1Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits32 aHigh, aLow, bHigh, bLow; + bits64 z0, zMiddleA, zMiddleB, z1; + + aLow = a; + aHigh = a>>32; + bLow = b; + bHigh = b>>32; + z1 = ( (bits64) aLow ) * bLow; + zMiddleA = ( (bits64) aLow ) * bHigh; + zMiddleB = ( (bits64) aHigh ) * bLow; + z0 = ( (bits64) aHigh ) * bHigh; + zMiddleA += zMiddleB; + z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); + zMiddleA <<= 32; + z1 += zMiddleA; + z0 += ( z1 < zMiddleA ); + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +`b' to obtain a 192-bit product. The product is broken into three 64-bit +pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +`z2Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + mul128By64To192( + bits64 a0, + bits64 a1, + bits64 b, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2, more1; + + mul64To128( a1, b, &z1, &z2 ); + mul64To128( a0, b, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the +128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit +product. The product is broken into four 64-bit pieces which are stored at +the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. +------------------------------------------------------------------------------- +*/ +INLINE void + mul128To256( + bits64 a0, + bits64 a1, + bits64 b0, + bits64 b1, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr, + bits64 *z3Ptr + ) +{ + bits64 z0, z1, z2, z3; + bits64 more1, more2; + + mul64To128( a1, b1, &z2, &z3 ); + mul64To128( a1, b0, &z1, &more2 ); + add128( z1, more2, 0, z2, &z1, &z2 ); + mul64To128( a0, b0, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + mul64To128( a0, b1, &more1, &more2 ); + add128( more1, more2, 0, z2, &more1, &z2 ); + add128( z0, z1, 0, more1, &z0, &z1 ); + *z3Ptr = z3; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/* +------------------------------------------------------------------------------- +Returns an approximation to the 64-bit integer quotient obtained by dividing +`b' into the 128-bit value formed by concatenating `a0' and `a1'. The +divisor `b' must be at least 2^63. If q is the exact quotient truncated +toward zero, the approximation returned lies between q and q + 2 inclusive. +If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +unsigned integer is returned. +------------------------------------------------------------------------------- +*/ +static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) +{ + bits64 b0, b1; + bits64 rem0, rem1, term0, term1; + bits64 z; + + if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); + b0 = b>>32; + z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; + mul64To128( b, z, &term0, &term1 ); + sub128( a0, a1, term0, term1, &rem0, &rem1 ); + while ( ( (sbits64) rem0 ) < 0 ) { + z -= LIT64( 0x100000000 ); + b1 = b<<32; + add128( rem0, rem1, b0, b1, &rem0, &rem1 ); + } + rem0 = ( rem0<<32 ) | ( rem1>>32 ); + z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; + return z; + +} + +#ifndef SOFTFLOAT_FOR_GCC /* Not used */ +/* +------------------------------------------------------------------------------- +Returns an approximation to the square root of the 32-bit significand given +by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of +`aExp' (the least significant bit) is 1, the integer returned approximates +2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' +is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either +case, the approximation returned lies strictly within +/-2 of the exact +value. +------------------------------------------------------------------------------- +*/ +static bits32 estimateSqrt32( int16 aExp, bits32 a ) +{ + static const bits16 sqrtOddAdjustments[] = { + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 + }; + static const bits16 sqrtEvenAdjustments[] = { + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 + }; + int8 index; + bits32 z; + + index = ( a>>27 ) & 15; + if ( aExp & 1 ) { + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; + z = ( ( a / z )<<14 ) + ( z<<15 ); + a >>= 1; + } + else { + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; + z = a / z + z; + z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); + if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); + } + return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); + +} +#endif + +/* +------------------------------------------------------------------------------- +Returns the number of leading 0 bits before the most-significant 1 bit of +`a'. If `a' is zero, 32 is returned. +------------------------------------------------------------------------------- +*/ +static int8 countLeadingZeros32( bits32 a ) +{ + static const int8 countLeadingZerosHigh[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int8 shiftCount; + + shiftCount = 0; + if ( a < 0x10000 ) { + shiftCount += 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZerosHigh[ a>>24 ]; + return shiftCount; + +} + +/* +------------------------------------------------------------------------------- +Returns the number of leading 0 bits before the most-significant 1 bit of +`a'. If `a' is zero, 64 is returned. +------------------------------------------------------------------------------- +*/ +static int8 countLeadingZeros64( bits64 a ) +{ + int8 shiftCount; + + shiftCount = 0; + if ( a < ( (bits64) 1 )<<32 ) { + shiftCount += 32; + } + else { + a >>= 32; + } + shiftCount += countLeadingZeros32( a ); + return shiftCount; + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' +is equal to the 128-bit value formed by concatenating `b0' and `b1'. +Otherwise, returns 0. +------------------------------------------------------------------------------- +*/ +INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 == b0 ) && ( a1 == b1 ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +than or equal to the 128-bit value formed by concatenating `b0' and `b1'. +Otherwise, returns 0. +------------------------------------------------------------------------------- +*/ +INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, +returns 0. +------------------------------------------------------------------------------- +*/ +INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is +not equal to the 128-bit value formed by concatenating `b0' and `b1'. +Otherwise, returns 0. +------------------------------------------------------------------------------- +*/ +INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 != b0 ) || ( a1 != b1 ); + +} + diff --git a/sys/lib/libkern/softfloat-specialize.h b/sys/lib/libkern/softfloat-specialize.h new file mode 100644 index 000000000..2efb8ffa7 --- /dev/null +++ b/sys/lib/libkern/softfloat-specialize.h @@ -0,0 +1,480 @@ +/* $NetBSD: softfloat-specialize.h,v 1.2 2008/04/28 20:24:06 martin Exp $ */ + +/* This is a derivative work. */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ross Harvey. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +=============================================================================== + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Underflow tininess-detection mode, statically initialized to default value. +------------------------------------------------------------------------------- +*/ + +/* [ MP safe, does not change dynamically ] */ +int float_detect_tininess = float_tininess_after_rounding; + +/* +------------------------------------------------------------------------------- +Internal canonical NaN format. +------------------------------------------------------------------------------- +*/ +typedef struct { + flag sign; + bits64 high, low; +} commonNaNT; + +/* +------------------------------------------------------------------------------- +The pattern for a default generated single-precision NaN. +------------------------------------------------------------------------------- +*/ +#define float32_default_nan 0xFFC00000 + +/* +------------------------------------------------------------------------------- +Returns 1 if the single-precision floating-point value `a' is a NaN; +otherwise returns 0. +------------------------------------------------------------------------------- +*/ +static flag float32_is_nan( float32 a ) +{ + + return ( 0xFF000000 < (bits32) ( a<<1 ) ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the single-precision floating-point value `a' is a signaling +NaN; otherwise returns 0. +------------------------------------------------------------------------------- +*/ +flag float32_is_signaling_nan( float32 a ) +{ + + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the single-precision floating-point NaN +`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +exception is raised. +------------------------------------------------------------------------------- +*/ +static commonNaNT float32ToCommonNaN( float32 a ) +{ + commonNaNT z; + + if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>31; + z.low = 0; + z.high = ( (bits64) a )<<41; + return z; + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the canonical NaN `a' to the single- +precision floating-point format. +------------------------------------------------------------------------------- +*/ +static float32 commonNaNToFloat32( commonNaNT a ) +{ + + return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); + +} + +/* +------------------------------------------------------------------------------- +Takes two single-precision floating-point values `a' and `b', one of which +is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +signaling NaN, the invalid exception is raised. +------------------------------------------------------------------------------- +*/ +static float32 propagateFloat32NaN( float32 a, float32 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float32_is_nan( a ); + aIsSignalingNaN = float32_is_signaling_nan( a ); + bIsNaN = float32_is_nan( b ); + bIsSignalingNaN = float32_is_signaling_nan( b ); + a |= 0x00400000; + b |= 0x00400000; + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; + if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; + return ( a < b ) ? a : b; + } + else { + return b; + } + +} + + +/* +------------------------------------------------------------------------------- +Returns the result of converting the double-precision floating-point NaN +`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +exception is raised. +------------------------------------------------------------------------------- +*/ +static commonNaNT float64ToCommonNaN( float64 a ) +{ + commonNaNT z; + + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>63; + z.low = 0; + z.high = a<<12; + return z; + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the canonical NaN `a' to the double- +precision floating-point format. +------------------------------------------------------------------------------- +*/ +static float64 commonNaNToFloat64( commonNaNT a ) +{ + + return + ( ( (bits64) a.sign )<<63 ) + | LIT64( 0x7FF8000000000000 ) + | ( a.high>>12 ); + +} + +/* +------------------------------------------------------------------------------- +Takes two double-precision floating-point values `a' and `b', one of which +is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +signaling NaN, the invalid exception is raised. +------------------------------------------------------------------------------- +*/ +static float64 propagateFloat64NaN( float64 a, float64 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float64_is_nan( a ); + aIsSignalingNaN = float64_is_signaling_nan( a ); + bIsNaN = float64_is_nan( b ); + bIsSignalingNaN = float64_is_signaling_nan( b ); + a |= LIT64( 0x0008000000000000 ); + b |= LIT64( 0x0008000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; + if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; + return ( a < b ) ? a : b; + } + else { + return b; + } + +} + +#ifdef FLOATX80 + +/* +------------------------------------------------------------------------------- +The pattern for a default generated extended double-precision NaN. The +`high' and `low' values hold the most- and least-significant bits, +respectively. +------------------------------------------------------------------------------- +*/ +#define floatx80_default_nan_high 0xFFFF +#define floatx80_default_nan_low LIT64( 0xC000000000000000 ) + +/* +------------------------------------------------------------------------------- +Returns 1 if the extended double-precision floating-point value `a' is a +NaN; otherwise returns 0. +------------------------------------------------------------------------------- +*/ +static flag floatx80_is_nan( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the extended double-precision floating-point value `a' is a +signaling NaN; otherwise returns 0. +------------------------------------------------------------------------------- +*/ +flag floatx80_is_signaling_nan( floatx80 a ) +{ + bits64 aLow; + + aLow = a.low & ~ LIT64( 0x4000000000000000 ); + return + ( ( a.high & 0x7FFF ) == 0x7FFF ) + && (bits64) ( aLow<<1 ) + && ( a.low == aLow ); + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the extended double-precision floating- +point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +invalid exception is raised. +------------------------------------------------------------------------------- +*/ +static commonNaNT floatx80ToCommonNaN( floatx80 a ) +{ + commonNaNT z; + + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>15; + z.low = 0; + z.high = a.low<<1; + return z; + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the canonical NaN `a' to the extended +double-precision floating-point format. +------------------------------------------------------------------------------- +*/ +static floatx80 commonNaNToFloatx80( commonNaNT a ) +{ + floatx80 z; + + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + return z; + +} + +/* +------------------------------------------------------------------------------- +Takes two extended double-precision floating-point values `a' and `b', one +of which is a NaN, and returns the appropriate NaN result. If either `a' or +`b' is a signaling NaN, the invalid exception is raised. +------------------------------------------------------------------------------- +*/ +static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = floatx80_is_nan( a ); + aIsSignalingNaN = floatx80_is_signaling_nan( a ); + bIsNaN = floatx80_is_nan( b ); + bIsSignalingNaN = floatx80_is_signaling_nan( b ); + a.low |= LIT64( 0xC000000000000000 ); + b.low |= LIT64( 0xC000000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( a.low < b.low ) return b; + if ( b.low < a.low ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + +#ifdef FLOAT128 + +/* +------------------------------------------------------------------------------- +The pattern for a default generated quadruple-precision NaN. The `high' and +`low' values hold the most- and least-significant bits, respectively. +------------------------------------------------------------------------------- +*/ +#define float128_default_nan_high LIT64( 0xFFFF800000000000 ) +#define float128_default_nan_low LIT64( 0x0000000000000000 ) + +/* +------------------------------------------------------------------------------- +Returns 1 if the quadruple-precision floating-point value `a' is a NaN; +otherwise returns 0. +------------------------------------------------------------------------------- +*/ +flag float128_is_nan( float128 a ) +{ + + return + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); + +} + +/* +------------------------------------------------------------------------------- +Returns 1 if the quadruple-precision floating-point value `a' is a +signaling NaN; otherwise returns 0. +------------------------------------------------------------------------------- +*/ +flag float128_is_signaling_nan( float128 a ) +{ + + return + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the quadruple-precision floating-point NaN +`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +exception is raised. +------------------------------------------------------------------------------- +*/ +static commonNaNT float128ToCommonNaN( float128 a ) +{ + commonNaNT z; + + if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>63; + shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); + return z; + +} + +/* +------------------------------------------------------------------------------- +Returns the result of converting the canonical NaN `a' to the quadruple- +precision floating-point format. +------------------------------------------------------------------------------- +*/ +static float128 commonNaNToFloat128( commonNaNT a ) +{ + float128 z; + + shift128Right( a.high, a.low, 16, &z.high, &z.low ); + z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); + return z; + +} + +/* +------------------------------------------------------------------------------- +Takes two quadruple-precision floating-point values `a' and `b', one of +which is a NaN, and returns the appropriate NaN result. If either `a' or +`b' is a signaling NaN, the invalid exception is raised. +------------------------------------------------------------------------------- +*/ +static float128 propagateFloat128NaN( float128 a, float128 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float128_is_nan( a ); + aIsSignalingNaN = float128_is_signaling_nan( a ); + bIsNaN = float128_is_nan( b ); + bIsSignalingNaN = float128_is_signaling_nan( b ); + a.high |= LIT64( 0x0000800000000000 ); + b.high |= LIT64( 0x0000800000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsSignalingNaN ) { + if ( bIsSignalingNaN ) goto returnLargerSignificand; + return bIsNaN ? b : a; + } + else if ( aIsNaN ) { + if ( bIsSignalingNaN | ! bIsNaN ) return a; + returnLargerSignificand: + if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; + if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; + return ( a.high < b.high ) ? a : b; + } + else { + return b; + } + +} + +#endif + diff --git a/sys/lib/libkern/softfloat.c b/sys/lib/libkern/softfloat.c new file mode 100644 index 000000000..43f64f385 --- /dev/null +++ b/sys/lib/libkern/softfloat.c @@ -0,0 +1,5502 @@ +/* $NetBSD: softfloat.c,v 1.4 2005/12/11 12:24:37 christos Exp $ */ + +/* + * This version hacked for use with gcc -msoft-float by bjh21. + * (Mostly a case of #ifdefing out things GCC doesn't need or provides + * itself). + */ + +/* + * Things you may want to define: + * + * SOFTFLOAT_FOR_GCC - build only those functions necessary for GCC (with + * -msoft-float) to work. Include "softfloat-for-gcc.h" to get them + * properly renamed. + */ + +/* +=============================================================================== + +This C source file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* If you need this in a boot program, you have bigger problems... */ +#ifndef _STANDALONE + +#include +#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<>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<>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<>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<>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<>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 ); + 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 ); + 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 ); + 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 ) & 63 ) ); + if ( (bits64) ( aSig1<>( - 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 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 ); + if ( aSig<<( shiftCount & 31 ) ) { + float_set_inexact(); + } + return z; + +} + +#endif + +#endif /* _STANDALONE */ diff --git a/sys/lib/libkern/softfloat.h b/sys/lib/libkern/softfloat.h new file mode 100644 index 000000000..94637c9a6 --- /dev/null +++ b/sys/lib/libkern/softfloat.h @@ -0,0 +1,363 @@ +/* $NetBSD: softfloat.h,v 1.4 2008/04/28 20:24:06 martin Exp $ */ + +/* This is a derivative work. */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ross Harvey. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* +=============================================================================== + +This C header file is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2a. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include + +#if !defined(_KERNEL) && !defined(_STANDALONE) +#include +#include +#else +#include "sys/inttypes.h" +#include "machine/ieeefp.h" +#endif +#include + +/* +------------------------------------------------------------------------------- +The macro `FLOATX80' must be defined to enable the extended double-precision +floating-point format `floatx80'. If this macro is not defined, the +`floatx80' type will not be defined, and none of the functions that either +input or output the `floatx80' type will be defined. The same applies to +the `FLOAT128' macro and the quadruple-precision format `float128'. +------------------------------------------------------------------------------- +*/ +/* #define FLOATX80 */ +/* #define FLOAT128 */ + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point types. +------------------------------------------------------------------------------- +*/ +typedef u_int32_t float32; +typedef u_int64_t float64; +#ifdef FLOATX80 +typedef struct { +#if BYTE_ORDER == BIG_ENDIAN + u_int16_t high; + u_int64_t low; +#else + u_int64_t low; + u_int16_t high; +#endif +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + u_int64_t high, low; +} float128; +#endif + +/* + * Some of the global variables that used to be here have been removed for + * fairly obvious (defopt-MULTIPROCESSOR) reasons. The rest (which don't + * change dynamically) will be removed later. [ross] + */ + +#define float_rounding_mode() fpgetround() + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point underflow tininess-detection mode. +------------------------------------------------------------------------------- +*/ + +extern int float_detect_tininess; +enum { + float_tininess_after_rounding = 1, + float_tininess_before_rounding = 0 +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point rounding mode. +------------------------------------------------------------------------------- +*/ + +enum { + float_round_nearest_even = FP_RN, + float_round_to_zero = FP_RZ, + float_round_down = FP_RM, + float_round_up = FP_RP +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE floating-point exception flags. +------------------------------------------------------------------------------- +*/ + +enum { + float_flag_inexact = FP_X_IMP, + float_flag_underflow = FP_X_UFL, + float_flag_overflow = FP_X_OFL, + float_flag_divbyzero = FP_X_DZ, + float_flag_invalid = FP_X_INV +}; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE integer-to-floating-point conversion routines. +------------------------------------------------------------------------------- +*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */ +float32 int64_to_float32( int64_t ); +float64 int64_to_float64( int64_t ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( int64_t ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( int64_t ); +#endif +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +int64_t float32_to_int64( float32 ); +int64_t float32_to_int64_round_to_zero( float32 ); +#endif +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE single-precision operations. +------------------------------------------------------------------------------- +*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +int float32_eq( float32, float32 ); +int float32_le( float32, float32 ); +int float32_lt( float32, float32 ); +int float32_eq_signaling( float32, float32 ); +int float32_le_quiet( float32, float32 ); +int float32_lt_quiet( float32, float32 ); +#ifndef SOFTFLOAT_FOR_GCC +int float32_is_signaling_nan( float32 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */ +int64_t float64_to_int64( float64 ); +int64_t float64_to_int64_round_to_zero( float64 ); +#endif +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE double-precision operations. +------------------------------------------------------------------------------- +*/ +#define float64_default_nan 0xFFF8000000000000LL + +static __inline int +float64_is_nan(float64 a) +{ + return 0xFFE0000000000000LL < a << 1; +} + +static __inline int +float64_is_signaling_nan(float64 a) +{ + return (a >> 51 & 0xFFF) == 0xFFE && (a & 0x0007FFFFFFFFFFFFLL); +} + +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +int float64_eq( float64, float64 ); +int float64_le( float64, float64 ); +int float64_lt( float64, float64 ); +int float64_eq_signaling( float64, float64 ); +int float64_le_quiet( float64, float64 ); +int float64_lt_quiet( float64, float64 ); +#ifndef SOFTFLOAT_FOR_GCC +int float64_is_signaling_nan( float64 ); +#endif + +#ifdef FLOATX80 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +int64_t floatx80_to_int64( floatx80 ); +int64_t floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision rounding precision. Valid +values are 32, 64, and 80. +------------------------------------------------------------------------------- +*/ +extern int floatx80_rounding_precision; + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE extended double-precision operations. +------------------------------------------------------------------------------- +*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +int floatx80_eq( floatx80, floatx80 ); +int floatx80_le( floatx80, floatx80 ); +int floatx80_lt( floatx80, floatx80 ); +int floatx80_eq_signaling( floatx80, floatx80 ); +int floatx80_le_quiet( floatx80, floatx80 ); +int floatx80_lt_quiet( floatx80, floatx80 ); +int floatx80_is_signaling_nan( floatx80 ); + +#endif + +#ifdef FLOAT128 + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision conversion routines. +------------------------------------------------------------------------------- +*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +int64_t float128_to_int64( float128 ); +int64_t float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/* +------------------------------------------------------------------------------- +Software IEC/IEEE quadruple-precision operations. +------------------------------------------------------------------------------- +*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +int float128_eq( float128, float128 ); +int float128_le( float128, float128 ); +int float128_lt( float128, float128 ); +int float128_eq_signaling( float128, float128 ); +int float128_le_quiet( float128, float128 ); +int float128_lt_quiet( float128, float128 ); +int float128_is_signaling_nan( float128 ); + +#endif + diff --git a/sys/lib/libkern/ulmax.c b/sys/lib/libkern/ulmax.c new file mode 100644 index 000000000..61f81d2e6 --- /dev/null +++ b/sys/lib/libkern/ulmax.c @@ -0,0 +1,41 @@ +/* $NetBSD: ulmax.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +unsigned long +ulmax(unsigned long a, unsigned long b) +{ + return (a > b ? a : b); +} diff --git a/sys/lib/libkern/ulmin.c b/sys/lib/libkern/ulmin.c new file mode 100644 index 000000000..c1afddd85 --- /dev/null +++ b/sys/lib/libkern/ulmin.c @@ -0,0 +1,41 @@ +/* $NetBSD: ulmin.c,v 1.6 2009/03/14 21:04:24 dsl Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91 + */ + +#define LIBKERN_INLINE +#include + +unsigned long +ulmin(unsigned long a, unsigned long b) +{ + return (a < b ? a : b); +} diff --git a/sys/lib/libkern/xlat_mbr_fstype.c b/sys/lib/libkern/xlat_mbr_fstype.c new file mode 100644 index 000000000..4151770db --- /dev/null +++ b/sys/lib/libkern/xlat_mbr_fstype.c @@ -0,0 +1,66 @@ +/* $NetBSD: xlat_mbr_fstype.c,v 1.7 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David Laight. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__KERNEL_RCSID(0,"$NetBSD: xlat_mbr_fstype.c,v 1.7 2008/04/28 20:24:06 martin Exp $"); + + +#include +#include + +int +xlat_mbr_fstype(int mbr_type) +{ + static const struct ptn_types { + uint8_t mbr_type; + uint8_t netbsd_type; + } ptn_types[] = { + { MBR_PTYPE_386BSD, FS_BSDFFS }, + { MBR_PTYPE_APPLE_UFS, FS_APPLEUFS }, + { MBR_PTYPE_FAT12, FS_MSDOS }, + { MBR_PTYPE_FAT16B, FS_MSDOS }, + { MBR_PTYPE_FAT16L, FS_MSDOS }, + { MBR_PTYPE_FAT16S, FS_MSDOS }, + { MBR_PTYPE_FAT32, FS_MSDOS }, + { MBR_PTYPE_FAT32L, FS_MSDOS }, + { MBR_PTYPE_LNXEXT2, FS_EX2FS }, + { MBR_PTYPE_LNXSWAP, FS_SWAP }, + { MBR_PTYPE_NETBSD, FS_BSDFFS }, + { MBR_PTYPE_NTFS, FS_NTFS }, + { MBR_PTYPE_MINIX_14B, FS_MINIXFS3 }, + { 0, FS_OTHER } + }; + const struct ptn_types *pt; + for (pt = ptn_types; pt->mbr_type != 0; pt++) + if (mbr_type == pt->mbr_type) + break; + return pt->netbsd_type; +} diff --git a/sys/lib/libsa/Makefile b/sys/lib/libsa/Makefile new file mode 100644 index 000000000..0eb99a79f --- /dev/null +++ b/sys/lib/libsa/Makefile @@ -0,0 +1,99 @@ +# $NetBSD: Makefile,v 1.76 2011/12/25 06:09:08 tsutsui Exp $ + +LIB= sa +NOPIC= # defined +NOPROFILE=# defined + +SA_USE_CREAD?= no # Read compressed kernels +SA_INCLUDE_NET?= yes # Netboot via TFTP, NFS +SA_USE_LOADFILE?= no # Generic executable loading support +SA_ENABLE_LS_OP?= no # Filesystems ls operation + +#DEBUGCPPFLAGS= -DBOOTP_DEBUG -DNETIF_DEBUG -DETHER_DEBUG -DNFS_DEBUG -DRPC_DEBUG -DRARP_DEBUG -DARP_DEBUG -DNET_DEBUG -DDEBUG -DPARANOID +CPPFLAGS= -I${SADIR} ${SACPPFLAGS} ${SAMISCCPPFLAGS} \ + -DCOMPAT_UFS ${DEBUGCPPFLAGS} + +#COPTS+= -ansi -pedantic -Wall + +.if defined(SA_EXTRADIR) +.-include "${SA_EXTRADIR}/Makefile.inc" +.endif + +.include + +.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 + +lib${LIB}.o:: ${OBJS} + @echo building standard ${LIB} library + @rm -f lib${LIB}.o + @${LD} -r -o lib${LIB}.o `lorder ${OBJS} | tsort` + +.if defined(HAVE_GCC) || defined(HAVE_PCC) +CPPFLAGS+= -Wno-pointer-sign +.endif + +.if defined(HAVE_GCC) && ${HAVE_GCC} >= 45 && ${MACHINE_ARCH} == "vax" +COPTS.bootp.c+= -O0 +.endif diff --git a/sys/lib/libsa/Makefile.inc b/sys/lib/libsa/Makefile.inc new file mode 100644 index 000000000..de37c63d1 --- /dev/null +++ b/sys/lib/libsa/Makefile.inc @@ -0,0 +1,87 @@ +# $NetBSD: Makefile.inc,v 1.20 2011/05/26 12:56:31 joerg Exp $ +# +# Configuration variables (default values are below): +# +# S must be set to the top of the 'sys' tree. +# SADST may be set to the location of the directory where library +# objects are to be built. Defaults to ${.OBJDIR}/lib/sa. +# SA_AS may be set to 'obj' to build a object from the library's +# object files. (Otherwise, a library will be built.) +# Defaults to 'library'. +# SAMISCCPPFLAGS +# Miscellaneous cpp flags to be passed to the library's Makefile +# when building. +# SAMISCMAKEFLAGS +# Miscellaneous flags to be passed to the library's Makefile when +# building. See library's Makefile for more details about +# supported flags and their default values. + +# Default values: +SADST?= ${.OBJDIR}/lib/sa +SA_AS?= library +SADOTDIR?= ../../. + +CWARNFLAGS.clang+= -Wno-format-extra-args + +SADIR= ${S:S@^.@${SADOTDIR}@:Q}/lib/libsa +.if (${SA_AS} == "obj") +SALIB= ${SADST}/libsa.o +SALIB_PROF= ${SADST}/libsa.po +.else +SALIB= ${SADST}/libsa.a +SALIB_PROF= ${SADST}/libsa_p.a +.endif +ZLIBSRCDIR:= ${.PARSEDIR}/../../../common/dist/zlib +SAMISCCPPFLAGS+=-I${ZLIBSRCDIR} + +SAMAKE= \ + cd ${SADST} && ${MAKE} -f ${SADIR:Q}/Makefile \ + SADIR=${SADIR:Q} \ + CC=${CC:Q} CFLAGS=${CFLAGS:Q} \ + AS=${AS:Q} AFLAGS=${AFLAGS:Q} \ + LORDER=${LORDER:Q} \ + TSORT=${TSORT:Q} \ + LD=${LD:Q} STRIP=${STRIP:Q} \ + AR=${AR:Q} NM=${NM:Q} \ + RANLIB=${RANLIB:Q} SIZE=${SIZE:Q} \ + MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \ + SACPPFLAGS=${CPPFLAGS:S@^-I.@-I${SADOTDIR}@g:Q} \ + SAMISCCPPFLAGS=${SAMISCCPPFLAGS:Q} \ + ${SAMISCMAKEFLAGS} + +${SALIB}: .NOTMAIN .MAKE __always_make_salib + @echo making sure the sa library is up to date... +.if (${SA_AS} == "library") + @${SAMAKE} libsa.a +.else + @${SAMAKE} libsa.o +.endif + +${SALIB_PROF}: .NOTMAIN .MAKE __always_make_salib + @echo making sure the profiled sa library is up to date... +.if (${SA_AS} == "library") + @${SAMAKE} libsa_p.a +.else + @${SAMAKE} libsa.po +.endif + +clean: .NOTMAIN cleansalib +cleansalib: .NOTMAIN + @echo cleaning the sa library objects + @if [ -d "${SADST}" ]; then ${SAMAKE} clean; fi + +cleandir distclean: .NOTMAIN cleandirsalib +cleandirsalib: .NOTMAIN + @echo cleandiring the sa library objects + @if [ -d "${SADST}" ]; then ${SAMAKE} cleandir; fi + +dependall depend: .NOTMAIN dependsalib +dependsalib: .NOTMAIN .MAKE __always_make_salib + @echo depending the sa library objects + @${SAMAKE} depend + +__always_make_salib: .NOTMAIN + @mkdir -p ${SADST} + +.PHONY: __always_make_salib +.PHONY: cleansalib cleandirsalib dependsalib diff --git a/sys/lib/libsa/alloc.c b/sys/lib/libsa/alloc.c new file mode 100644 index 000000000..a818542d8 --- /dev/null +++ b/sys/lib/libsa/alloc.c @@ -0,0 +1,269 @@ +/* $NetBSD: alloc.c,v 1.26 2011/07/30 03:43:20 jakllsch Exp $ */ + +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)alloc.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)alloc.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Dynamic memory allocator. + * + * Compile options: + * + * ALLOC_TRACE enable tracing of allocations/deallocations + + * ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than + * the default best-fit algorithm. + * + * HEAP_LIMIT heap limit address (defaults to "no limit"). + * + * HEAP_START start address of heap (defaults to '&end'). + * + * DEBUG enable debugging sanity checks. + */ + +#include +#include "stand.h" + +/* + * Each block actually has ALIGN(unsigned int) + ALIGN(size) bytes allocated + * to it, as follows: + * + * 0 ... (sizeof(unsigned int) - 1) + * allocated or unallocated: holds size of user-data part of block. + * + * sizeof(unsigned int) ... (ALIGN(sizeof(unsigned int)) - 1) + * allocated: unused + * unallocated: depends on packing of struct fl + * + * ALIGN(sizeof(unsigned int)) ... + * (ALIGN(sizeof(unsigned int)) + ALIGN(data size) - 1) + * allocated: user data + * unallocated: depends on packing of struct fl + * + * 'next' is only used when the block is unallocated (i.e. on the free list). + * However, note that ALIGN(sizeof(unsigned int)) + ALIGN(data size) must + * be at least 'sizeof(struct fl)', so that blocks can be used as structures + * when on the free list. + */ +struct fl { + unsigned int size; + struct fl *next; +} *freelist; + +#ifdef HEAP_VARIABLE +static char *top, *heapstart, *heaplimit; +void +setheap(void *start, void *limit) +{ + heapstart = top = start; + heaplimit = limit; +} +#define HEAP_START heapstart +#define HEAP_LIMIT heaplimit +#else /* !HEAP_VARIABLE */ +#ifndef HEAP_START +extern char end[]; +#define HEAP_START end +#endif +static char *top = (char *)HEAP_START; +#endif /* HEAP_VARIABLE */ + +__compactcall void * +alloc(size_t size) +{ + struct fl **f = &freelist, **bestf = NULL; +#ifndef ALLOC_FIRST_FIT + unsigned int bestsize = 0xffffffff; /* greater than any real size */ +#endif + char *help; + int failed; + +#ifdef ALLOC_TRACE + printf("alloc(%zu)", size); +#endif + +#ifdef ALLOC_FIRST_FIT + while (*f != (struct fl *)0 && (size_t)(*f)->size < size) + f = &((*f)->next); + bestf = f; + failed = (*bestf == (struct fl *)0); +#else + /* scan freelist */ + while (*f) { + if ((size_t)(*f)->size >= size) { + if ((size_t)(*f)->size == size) /* exact match */ + goto found; + + if ((*f)->size < bestsize) { + /* keep best fit */ + bestf = f; + bestsize = (*f)->size; + } + } + f = &((*f)->next); + } + + /* no match in freelist if bestsize unchanged */ + failed = (bestsize == 0xffffffff); +#endif + + if (failed) { /* nothing found */ + /* + * allocate from heap, keep chunk len in + * first word + */ + help = top; + + /* make _sure_ the region can hold a struct fl. */ + if (size < ALIGN(sizeof (struct fl *))) + size = ALIGN(sizeof (struct fl *)); + top += ALIGN(sizeof(unsigned int)) + ALIGN(size); +#ifdef HEAP_LIMIT + if (top > (char *)HEAP_LIMIT) + panic("heap full (%p+%zu)", help, size); +#endif + *(unsigned int *)(void *)help = (unsigned int)ALIGN(size); +#ifdef ALLOC_TRACE + printf("=%lx\n", (u_long)help + ALIGN(sizeof(unsigned int))); +#endif + return help + ALIGN(sizeof(unsigned int)); + } + + /* we take the best fit */ + f = bestf; + +#ifndef ALLOC_FIRST_FIT +found: +#endif + /* remove from freelist */ + help = (char *)(void *)*f; + *f = (*f)->next; +#ifdef ALLOC_TRACE + printf("=%lx (origsize %u)\n", + (u_long)help + ALIGN(sizeof(unsigned int)), *(unsigned int *)help); +#endif + return help + ALIGN(sizeof(unsigned int)); +} + +__compactcall void +/*ARGSUSED*/ +dealloc(void *ptr, size_t size) +{ + struct fl *f = + (struct fl *)(void *)((char *)(void *)ptr - + ALIGN(sizeof(unsigned int))); +#ifdef ALLOC_TRACE + printf("dealloc(%lx, %zu) (origsize %u)\n", (u_long)ptr, size, f->size); +#endif +#ifdef DEBUG + if (size > (size_t)f->size) { + printf("dealloc %zu bytes @%lx, should be <=%u\n", + size, (u_long)ptr, f->size); + } + + if (ptr < (void *)HEAP_START) + printf("dealloc: %lx before start of heap.\n", (u_long)ptr); + +#ifdef HEAP_LIMIT + if (ptr > (void *)HEAP_LIMIT) + printf("dealloc: %lx beyond end of heap.\n", (u_long)ptr); +#endif +#endif /* DEBUG */ + /* put into freelist */ + f->next = freelist; + freelist = f; +} diff --git a/sys/lib/libsa/arp.c b/sys/lib/libsa/arp.c new file mode 100644 index 000000000..8716fd6e1 --- /dev/null +++ b/sys/lib/libsa/arp.c @@ -0,0 +1,323 @@ +/* $NetBSD: arp.c,v 1.33 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL) + */ + +#include +#include +#include +#include +#include + +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "net.h" + +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +/* Cache stuff */ +#define ARP_NUM 8 /* need at most 3 arp entries */ + +struct arp_list { + struct in_addr addr; + u_char ea[6]; +} arp_list[ARP_NUM] = { + /* XXX - net order `INADDR_BROADCAST' must be a constant */ + { {0xffffffff}, BA } +}; +int arp_num = 1; + +/* Local forwards */ +static ssize_t arpsend(struct iodesc *, void *, size_t); +static ssize_t arprecv(struct iodesc *, void *, size_t, saseconds_t); + +/* Broadcast an ARP packet, asking who has addr on interface d */ +u_char * +arpwhohas(struct iodesc *d, struct in_addr addr) +{ + int i; + struct ether_arp *ah; + struct arp_list *al; + struct { + struct ether_header eh; + struct { + struct ether_arp arp; + u_char pad[18]; /* 60 - sizeof(...) */ + } data; + } wbuf; + struct { + struct ether_header eh; + struct { + struct ether_arp arp; + u_char pad[24]; /* extra space */ + } data; + } rbuf; + + /* Try for cached answer first */ + for (i = 0, al = arp_list; i < arp_num; ++i, ++al) + if (addr.s_addr == al->addr.s_addr) + return al->ea; + + /* Don't overflow cache */ + if (arp_num > ARP_NUM - 1) { + arp_num = 1; /* recycle */ + printf("arpwhohas: overflowed arp_list!\n"); + } + +#ifdef ARP_DEBUG + if (debug) + printf("arpwhohas: send request for %s\n", inet_ntoa(addr)); +#endif + + (void)memset(&wbuf.data, 0, sizeof(wbuf.data)); + ah = &wbuf.data.arp; + ah->arp_hrd = htons(ARPHRD_ETHER); + ah->arp_pro = htons(ETHERTYPE_IP); + ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */ + ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */ + ah->arp_op = htons(ARPOP_REQUEST); + MACPY(d->myea, ah->arp_sha); + (void)memcpy(ah->arp_spa, &d->myip, sizeof(ah->arp_spa)); + /* Leave zeros in arp_tha */ + (void)memcpy(ah->arp_tpa, &addr, sizeof(ah->arp_tpa)); + + /* Store ip address in cache (incomplete entry). */ + al->addr = addr; + + i = sendrecv(d, + arpsend, &wbuf.data, sizeof(wbuf.data), + arprecv, &rbuf.data, sizeof(rbuf.data)); + if (i == -1) { + panic("arp: no response for %s", + inet_ntoa(addr)); + } + + /* Store ethernet address in cache */ + ah = &rbuf.data.arp; +#ifdef ARP_DEBUG + if (debug) { + printf("arp: response from %s\n", + ether_sprintf(rbuf.eh.ether_shost)); + printf("arp: cacheing %s --> %s\n", + inet_ntoa(addr), ether_sprintf(ah->arp_sha)); + } +#endif + MACPY(ah->arp_sha, al->ea); + ++arp_num; + + return al->ea; +} + +static ssize_t +arpsend(struct iodesc *d, void *pkt, size_t len) +{ + +#ifdef ARP_DEBUG + if (debug) + printf("arpsend: called\n"); +#endif + + return sendether(d, pkt, len, bcea, ETHERTYPE_ARP); +} + +/* + * Returns 0 if this is the packet we're waiting for + * else -1 (and errno == 0) + */ +static ssize_t +arprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + ssize_t n; + struct ether_arp *ah; + u_int16_t etype; /* host order */ + +#ifdef ARP_DEBUG + if (debug) + printf("arprecv: "); +#endif + + n = readether(d, pkt, len, tleft, &etype); + errno = 0; /* XXX */ + if (n == -1 || (size_t)n < sizeof(struct ether_arp)) { +#ifdef ARP_DEBUG + if (debug) + printf("bad len=%ld\n", (signed long) n); +#endif + return -1; + } + + if (etype != ETHERTYPE_ARP) { +#ifdef ARP_DEBUG + if (debug) + printf("not arp type=%d\n", etype); +#endif + return -1; + } + + /* Ethernet address now checked in readether() */ + + ah = (struct ether_arp *)pkt; + if (ah->arp_hrd != htons(ARPHRD_ETHER) || + ah->arp_pro != htons(ETHERTYPE_IP) || + ah->arp_hln != sizeof(ah->arp_sha) || + ah->arp_pln != sizeof(ah->arp_spa) ) + { +#ifdef ARP_DEBUG + if (debug) + printf("bad hrd/pro/hln/pln\n"); +#endif + return -1; + } + + if (ah->arp_op == htons(ARPOP_REQUEST)) { +#ifdef ARP_DEBUG + if (debug) + printf("is request\n"); +#endif + arp_reply(d, ah); + return -1; + } + + if (ah->arp_op != htons(ARPOP_REPLY)) { +#ifdef ARP_DEBUG + if (debug) + printf("not ARP reply\n"); +#endif + return -1; + } + + /* Is the reply from the source we want? */ + if (memcmp(&arp_list[arp_num].addr, + ah->arp_spa, sizeof(ah->arp_spa))) + { +#ifdef ARP_DEBUG + if (debug) + printf("unwanted address\n"); +#endif + return -1; + } + /* We don't care who the reply was sent to. */ + + /* We have our answer. */ +#ifdef ARP_DEBUG + if (debug) + printf("got it\n"); +#endif + return n; +} + +/* + * Convert an ARP request into a reply and send it. + * Notes: Re-uses buffer. Pad to length = 46. + */ +void +arp_reply(struct iodesc *d, void *pkt) +{ + struct ether_arp *arp = pkt; + + if (arp->arp_hrd != htons(ARPHRD_ETHER) || + arp->arp_pro != htons(ETHERTYPE_IP) || + arp->arp_hln != sizeof(arp->arp_sha) || + arp->arp_pln != sizeof(arp->arp_spa) ) + { +#ifdef ARP_DEBUG + if (debug) + printf("arp_reply: bad hrd/pro/hln/pln\n"); +#endif + return; + } + + if (arp->arp_op != htons(ARPOP_REQUEST)) { +#ifdef ARP_DEBUG + if (debug) + printf("arp_reply: not request!\n"); +#endif + return; + } + + /* If we are not the target, ignore the request. */ + if (memcmp(arp->arp_tpa, &d->myip, sizeof(arp->arp_tpa))) + return; + +#ifdef ARP_DEBUG + if (debug) { + printf("arp_reply: to %s\n", ether_sprintf(arp->arp_sha)); + } +#endif + + arp->arp_op = htons(ARPOP_REPLY); + /* source becomes target */ + (void)memcpy(arp->arp_tha, arp->arp_sha, sizeof(arp->arp_tha)); + (void)memcpy(arp->arp_tpa, arp->arp_spa, sizeof(arp->arp_tpa)); + /* here becomes source */ + (void)memcpy(arp->arp_sha, d->myea, sizeof(arp->arp_sha)); + (void)memcpy(arp->arp_spa, &d->myip, sizeof(arp->arp_spa)); + + /* + * No need to get fancy here. If the send fails, the + * requestor will just ask again. + */ + (void) sendether(d, pkt, sizeof(*arp) + 18, + arp->arp_tha, ETHERTYPE_ARP); +} diff --git a/sys/lib/libsa/bootp.c b/sys/lib/libsa/bootp.c new file mode 100644 index 000000000..c7c9afebd --- /dev/null +++ b/sys/lib/libsa/bootp.c @@ -0,0 +1,447 @@ +/* $NetBSD: bootp.c,v 1.38 2011/05/11 16:23:40 zoltan Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp (LBL) + */ + +#include +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "net.h" +#include "bootp.h" + +struct in_addr servip; +#ifdef SUPPORT_LINUX +char linuxcmdline[256]; +#ifndef TAG_LINUX_CMDLINE +#define TAG_LINUX_CMDLINE 123 +#endif +#endif + +static n_long nmask, smask; + +static satime_t bot; + +static char vm_rfc1048[4] = VM_RFC1048; +#ifdef BOOTP_VEND_CMU +static char vm_cmu[4] = VM_CMU; +#endif + +/* Local forwards */ +static ssize_t bootpsend(struct iodesc *, void *, size_t); +static ssize_t bootprecv(struct iodesc *, void *, size_t, saseconds_t); +static int vend_rfc1048(u_char *, u_int); +#ifdef BOOTP_VEND_CMU +static void vend_cmu(u_char *); +#endif + +#ifdef SUPPORT_DHCP +static char expected_dhcpmsgtype = -1, dhcp_ok; +struct in_addr dhcp_serverip; +#endif + +/* + * Boot programs can patch this at run-time to change the behavior + * of bootp/dhcp. + */ +int bootp_flags; + +static void +bootp_addvend(u_char *area) +{ +#ifdef SUPPORT_DHCP + char vci[64]; + int vcilen; + + *area++ = TAG_PARAM_REQ; + *area++ = 6; + *area++ = TAG_SUBNET_MASK; + *area++ = TAG_GATEWAY; + *area++ = TAG_HOSTNAME; + *area++ = TAG_DOMAINNAME; + *area++ = TAG_ROOTPATH; + *area++ = TAG_SWAPSERVER; + + /* Insert a NetBSD Vendor Class Identifier option. */ + sprintf(vci, "NetBSD:%s:libsa", MACHINE); + vcilen = strlen(vci); + *area++ = TAG_CLASSID; + *area++ = vcilen; + (void)memcpy(area, vci, vcilen); + area += vcilen; +#endif + *area = TAG_END; +} + +/* Fetch required bootp information */ +void +bootp(int sock) +{ + struct iodesc *d; + struct bootp *bp; + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct bootp wbootp; + } wbuf; + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct bootp rbootp; + } rbuf; + unsigned int index; + +#ifdef BOOTP_DEBUG + if (debug) + printf("bootp: socket=%d\n", sock); +#endif + if (!bot) + bot = getsecs(); + + if (!(d = socktodesc(sock))) { + printf("bootp: bad socket. %d\n", sock); + return; + } +#ifdef BOOTP_DEBUG + if (debug) + printf("bootp: d=%lx\n", (long)d); +#endif + + bp = &wbuf.wbootp; + (void)memset(bp, 0, sizeof(*bp)); + + bp->bp_op = BOOTREQUEST; + bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ + bp->bp_hlen = 6; + bp->bp_xid = htonl(d->xid); + MACPY(d->myea, bp->bp_chaddr); + (void)strncpy((char *)bp->bp_file, bootfile, sizeof(bp->bp_file)); + (void)memcpy(bp->bp_vend, vm_rfc1048, sizeof(vm_rfc1048)); + index = 4; +#ifdef SUPPORT_DHCP + bp->bp_vend[index++] = TAG_DHCP_MSGTYPE; + bp->bp_vend[index++] = 1; + bp->bp_vend[index++] = DHCPDISCOVER; +#endif + bootp_addvend(&bp->bp_vend[index]); + + d->myip.s_addr = INADDR_ANY; + d->myport = htons(IPPORT_BOOTPC); + d->destip.s_addr = INADDR_BROADCAST; + d->destport = htons(IPPORT_BOOTPS); + +#ifdef SUPPORT_DHCP + expected_dhcpmsgtype = DHCPOFFER; + dhcp_ok = 0; +#endif + + if (sendrecv(d, + bootpsend, bp, sizeof(*bp), + bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) + == -1) { + printf("bootp: no reply\n"); + return; + } + +#ifdef SUPPORT_DHCP + if (dhcp_ok) { + u_int32_t leasetime; + index = 6; + bp->bp_vend[index++] = DHCPREQUEST; + bp->bp_vend[index++] = TAG_REQ_ADDR; + bp->bp_vend[index++] = 4; + (void)memcpy(&bp->bp_vend[9], &rbuf.rbootp.bp_yiaddr, 4); + index += 4; + bp->bp_vend[index++] = TAG_SERVERID; + bp->bp_vend[index++] = 4; + (void)memcpy(&bp->bp_vend[index], &dhcp_serverip.s_addr, 4); + index += 4; + bp->bp_vend[index++] = TAG_LEASETIME; + bp->bp_vend[index++] = 4; + leasetime = htonl(300); + (void)memcpy(&bp->bp_vend[index], &leasetime, 4); + index += 4; + bootp_addvend(&bp->bp_vend[index]); + + expected_dhcpmsgtype = DHCPACK; + + if (sendrecv(d, + bootpsend, bp, sizeof(*bp), + bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp)) + == -1) { + printf("DHCPREQUEST failed\n"); + return; + } + } +#endif + + myip = d->myip = rbuf.rbootp.bp_yiaddr; + servip = rbuf.rbootp.bp_siaddr; + if (rootip.s_addr == INADDR_ANY) + rootip = servip; + (void)memcpy(bootfile, rbuf.rbootp.bp_file, sizeof(bootfile)); + bootfile[sizeof(bootfile) - 1] = '\0'; + + if (IN_CLASSA(myip.s_addr)) + nmask = IN_CLASSA_NET; + else if (IN_CLASSB(myip.s_addr)) + nmask = IN_CLASSB_NET; + else + nmask = IN_CLASSC_NET; +#ifdef BOOTP_DEBUG + if (debug) + printf("'native netmask' is %s\n", intoa(nmask)); +#endif + + /* Get subnet (or natural net) mask */ + netmask = nmask; + if (smask) + netmask = smask; +#ifdef BOOTP_DEBUG + if (debug) + printf("mask: %s\n", intoa(netmask)); +#endif + + /* We need a gateway if root is on a different net */ + if (!SAMENET(myip, rootip, netmask)) { +#ifdef BOOTP_DEBUG + if (debug) + printf("need gateway for root ip\n"); +#endif + } + + /* Toss gateway if on a different net */ + if (!SAMENET(myip, gateip, netmask)) { +#ifdef BOOTP_DEBUG + if (debug) + printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); +#endif + gateip.s_addr = 0; + } + +#ifdef BOOTP_DEBUG + if (debug) { + printf("client addr: %s\n", inet_ntoa(myip)); + if (smask) + printf("subnet mask: %s\n", intoa(smask)); + if (gateip.s_addr != 0) + printf("net gateway: %s\n", inet_ntoa(gateip)); + printf("server addr: %s\n", inet_ntoa(rootip)); + if (rootpath[0] != '\0') + printf("server path: %s\n", rootpath); + if (bootfile[0] != '\0') + printf("file name: %s\n", bootfile); + } +#endif + + /* Bump xid so next request will be unique. */ + ++d->xid; +} + +/* Transmit a bootp request */ +static ssize_t +bootpsend(struct iodesc *d, void *pkt, size_t len) +{ + struct bootp *bp; + +#ifdef BOOTP_DEBUG + if (debug) + printf("bootpsend: d=%lx called.\n", (long)d); +#endif + + bp = pkt; + bp->bp_secs = htons((u_short)(getsecs() - bot)); + +#ifdef BOOTP_DEBUG + if (debug) + printf("bootpsend: calling sendudp\n"); +#endif + + return sendudp(d, pkt, len); +} + +static ssize_t +bootprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + ssize_t n; + struct bootp *bp; + +#ifdef BOOTP_DEBUGx + if (debug) + printf("bootp_recvoffer: called\n"); +#endif + + n = readudp(d, pkt, len, tleft); + if (n == -1 || (size_t)n < sizeof(struct bootp) - BOOTP_VENDSIZE) + goto bad; + + bp = (struct bootp *)pkt; + +#ifdef BOOTP_DEBUG + if (debug) + printf("bootprecv: checked. bp = 0x%lx, n = %d\n", + (long)bp, (int)n); +#endif + if (bp->bp_xid != htonl(d->xid)) { +#ifdef BOOTP_DEBUG + if (debug) { + printf("bootprecv: expected xid 0x%lx, got 0x%x\n", + d->xid, ntohl(bp->bp_xid)); + } +#endif + goto bad; + } + + /* protect against bogus addresses sent by DHCP servers */ + if (bp->bp_yiaddr.s_addr == INADDR_ANY || + bp->bp_yiaddr.s_addr == INADDR_BROADCAST) + goto bad; + +#ifdef BOOTP_DEBUG + if (debug) + printf("bootprecv: got one!\n"); +#endif + + /* Suck out vendor info */ + if (memcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) { + if (vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0) + goto bad; + } +#ifdef BOOTP_VEND_CMU + else if (memcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0) + vend_cmu(bp->bp_vend); +#endif + else + printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend); + + return n; +bad: + errno = 0; + return -1; +} + +static int +vend_rfc1048(u_char *cp, u_int len) +{ + u_char *ep; + int size; + u_char tag; + +#ifdef BOOTP_DEBUG + if (debug) + printf("vend_rfc1048 bootp info. len=%d\n", len); +#endif + ep = cp + len; + + /* Step over magic cookie */ + cp += sizeof(int); + + while (cp < ep) { + tag = *cp++; + size = *cp++; + if (tag == TAG_END) + break; + + if (tag == TAG_SUBNET_MASK && size >= sizeof(smask)) { + (void)memcpy(&smask, cp, sizeof(smask)); + } + if (tag == TAG_GATEWAY && size >= sizeof(gateip.s_addr)) { + (void)memcpy(&gateip.s_addr, cp, sizeof(gateip.s_addr)); + } + if (tag == TAG_SWAPSERVER && size >= sizeof(rootip.s_addr)) { + /* let it override bp_siaddr */ + (void)memcpy(&rootip.s_addr, cp, sizeof(rootip.s_addr)); + } + if (tag == TAG_ROOTPATH && size < sizeof(rootpath)) { + strncpy(rootpath, (char *)cp, sizeof(rootpath)); + rootpath[size] = '\0'; + } + if (tag == TAG_HOSTNAME && size < sizeof(hostname)) { + strncpy(hostname, (char *)cp, sizeof(hostname)); + hostname[size] = '\0'; + } +#ifdef SUPPORT_DHCP + if (tag == TAG_DHCP_MSGTYPE) { + if (*cp != expected_dhcpmsgtype) + return -1; + dhcp_ok = 1; + } + if (tag == TAG_SERVERID && + size >= sizeof(dhcp_serverip.s_addr)) + { + (void)memcpy(&dhcp_serverip.s_addr, cp, + sizeof(dhcp_serverip.s_addr)); + } +#endif +#ifdef SUPPORT_LINUX + if (tag == TAG_LINUX_CMDLINE && size < sizeof(linuxcmdline)) { + strncpy(linuxcmdline, (char *)cp, sizeof(linuxcmdline)); + linuxcmdline[size] = '\0'; + } +#endif + cp += size; + } + return 0; +} + +#ifdef BOOTP_VEND_CMU +static void +vend_cmu(u_char *cp) +{ + struct cmu_vend *vp; + +#ifdef BOOTP_DEBUG + if (debug) + printf("vend_cmu bootp info.\n"); +#endif + vp = (struct cmu_vend *)cp; + + if (vp->v_smask.s_addr != 0) { + smask = vp->v_smask.s_addr; + } + if (vp->v_dgate.s_addr != 0) { + gateip = vp->v_dgate; + } +} +#endif diff --git a/sys/lib/libsa/bootp.h b/sys/lib/libsa/bootp.h new file mode 100644 index 000000000..50fadcacc --- /dev/null +++ b/sys/lib/libsa/bootp.h @@ -0,0 +1,138 @@ +/* $NetBSD: bootp.h,v 1.9 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Bootstrap Protocol (BOOTP). RFC951 and RFC1048. + * + * This file specifies the "implementation-independent" BOOTP protocol + * information which is common to both client and server. + * + * Copyright 1988 by Carnegie Mellon. + * + * Permission to use, copy, modify, and distribute this program for any + * purpose and without fee is hereby granted, provided that this copyright + * and permission notice appear on all copies and supporting documentation, + * the name of Carnegie Mellon not be used in advertising or publicity + * pertaining to distribution of the program without specific prior + * permission, and notice be given in supporting documentation that copying + * and distribution is by permission of Carnegie Mellon and Stanford + * University. Carnegie Mellon makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + + +struct bootp { + unsigned char bp_op; /* packet opcode type */ + unsigned char bp_htype; /* hardware addr type */ + unsigned char bp_hlen; /* hardware addr length */ + unsigned char bp_hops; /* gateway hops */ + unsigned int bp_xid; /* transaction ID */ + unsigned short bp_secs; /* seconds since boot began */ + unsigned short bp_flags; + struct in_addr bp_ciaddr; /* client IP address */ + struct in_addr bp_yiaddr; /* 'your' IP address */ + struct in_addr bp_siaddr; /* server IP address */ + struct in_addr bp_giaddr; /* gateway IP address */ + unsigned char bp_chaddr[16]; /* client hardware address */ + unsigned char bp_sname[64]; /* server host name */ + unsigned char bp_file[128]; /* boot file name */ +#ifdef SUPPORT_DHCP +#define BOOTP_VENDSIZE 312 +#else +#define BOOTP_VENDSIZE 64 +#endif + unsigned char bp_vend[BOOTP_VENDSIZE]; /* vendor-specific area */ +}; + +/* + * UDP port numbers, server and client. + */ +#define IPPORT_BOOTPS 67 +#define IPPORT_BOOTPC 68 + +#define BOOTREPLY 2 +#define BOOTREQUEST 1 + + +/* + * Vendor magic cookie (v_magic) for CMU + */ +#define VM_CMU "CMU" + +/* + * Vendor magic cookie (v_magic) for RFC1048 + */ +#define VM_RFC1048 { 99, 130, 83, 99 } + + +/* + * RFC1048 tag values used to specify what information is being supplied in + * the vendor field of the packet. + */ + +#define TAG_PAD ((unsigned char) 0) +#define TAG_SUBNET_MASK ((unsigned char) 1) +#define TAG_TIME_OFFSET ((unsigned char) 2) +#define TAG_GATEWAY ((unsigned char) 3) +#define TAG_TIME_SERVER ((unsigned char) 4) +#define TAG_NAME_SERVER ((unsigned char) 5) +#define TAG_DOMAIN_SERVER ((unsigned char) 6) +#define TAG_LOG_SERVER ((unsigned char) 7) +#define TAG_COOKIE_SERVER ((unsigned char) 8) +#define TAG_LPR_SERVER ((unsigned char) 9) +#define TAG_IMPRESS_SERVER ((unsigned char) 10) +#define TAG_RLP_SERVER ((unsigned char) 11) +#define TAG_HOSTNAME ((unsigned char) 12) +#define TAG_BOOTSIZE ((unsigned char) 13) +#define TAG_DUMPFILE ((unsigned char) 14) +#define TAG_DOMAINNAME ((unsigned char) 15) +#define TAG_SWAPSERVER ((unsigned char) 16) +#define TAG_ROOTPATH ((unsigned char) 17) + +#ifdef SUPPORT_DHCP +#define TAG_REQ_ADDR ((unsigned char) 50) +#define TAG_LEASETIME ((unsigned char) 51) +#define TAG_OVERLOAD ((unsigned char) 52) +#define TAG_DHCP_MSGTYPE ((unsigned char) 53) +#define TAG_SERVERID ((unsigned char) 54) +#define TAG_PARAM_REQ ((unsigned char) 55) +#define TAG_MSG ((unsigned char) 56) +#define TAG_MAXSIZE ((unsigned char) 57) +#define TAG_T1 ((unsigned char) 58) +#define TAG_T2 ((unsigned char) 59) +#define TAG_CLASSID ((unsigned char) 60) +#define TAG_CLIENTID ((unsigned char) 61) +#endif + +#define TAG_END ((unsigned char) 255) + +#ifdef SUPPORT_DHCP +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#endif + +/* + * "vendor" data permitted for CMU bootp clients. + */ + +struct cmu_vend { + unsigned char v_magic[4]; /* magic number */ + unsigned int v_flags; /* flags/opcodes, etc. */ + struct in_addr v_smask; /* Subnet mask */ + struct in_addr v_dgate; /* Default gateway */ + struct in_addr v_dns1, v_dns2; /* Domain name servers */ + struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */ + struct in_addr v_ts1, v_ts2; /* Time servers */ + unsigned char v_unused[25]; /* currently unused */ +}; + + +/* v_flags values */ +#define VF_SMASK 1 /* Subnet mask field contains valid data */ + +extern void bootp(int); diff --git a/sys/lib/libsa/bootparam.c b/sys/lib/libsa/bootparam.c new file mode 100644 index 000000000..8c6b9184a --- /dev/null +++ b/sys/lib/libsa/bootparam.c @@ -0,0 +1,439 @@ +/* $NetBSD: bootparam.c,v 1.19 2009/10/21 23:12:10 snj Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * RPC/bootparams + */ + +#include +#include + +#include + +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "rpcv2.h" + +#include "stand.h" +#include "net.h" +#include "rpc.h" +#include "bootparam.h" + +#ifdef DEBUG_RPC +#define RPC_PRINTF(a) printf a +#else +#define RPC_PRINTF(a) +#endif + +struct in_addr bp_server_addr; /* net order */ +n_short bp_server_port; /* net order */ + +int hostnamelen; +char domainname[FNAME_SIZE]; /* our DNS domain */ +int domainnamelen; + +/* + * RPC definitions for bootparamd + */ +#define BOOTPARAM_PROG 100026 +#define BOOTPARAM_VERS 1 +#define BOOTPARAM_WHOAMI 1 +#define BOOTPARAM_GETFILE 2 + +/* + * Inet address in RPC messages + * (Note, really four ints, NOT chars. Blech.) + */ +struct xdr_inaddr { + u_int32_t atype; + int32_t addr[4]; +}; + +int xdr_inaddr_encode(char **, struct in_addr); +int xdr_inaddr_decode(char **, struct in_addr *); + +int xdr_string_encode(char **, char *, int); +int xdr_string_decode(char **, char *, int *); + + +/* + * RPC: bootparam/whoami + * Given client IP address, get: + * client name (hostname) + * domain name (domainname) + * gateway address + * + * The hostname and domainname are set here for convenience. + * + * Note - bpsin is initialized to the broadcast address, + * and will be replaced with the bootparam server address + * after this call is complete. Have to use PMAP_PROC_CALL + * to make sure we get responses only from a servers that + * know about us (don't want to broadcast a getport call). + */ +int +bp_whoami(int sockfd) +{ + /* RPC structures for PMAPPROC_CALLIT */ + struct args { + u_int32_t prog; + u_int32_t vers; + u_int32_t proc; + u_int32_t arglen; + struct xdr_inaddr xina; + } *args; + struct repl { + u_int16_t _pad; + u_int16_t port; + u_int32_t encap_len; + /* encapsulated data here */ + n_long capsule[64]; + } *repl; + struct { + n_long h[RPC_HEADER_WORDS]; + struct args d; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct repl d; + } rdata; + char *send_tail, *recv_head; + struct iodesc *d; + int len, x; + + RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip))); + + if (!(d = socktodesc(sockfd))) { + RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd)); + return -1; + } + args = &sdata.d; + repl = &rdata.d; + + /* + * Build request args for PMAPPROC_CALLIT. + */ + args->prog = htonl(BOOTPARAM_PROG); + args->vers = htonl(BOOTPARAM_VERS); + args->proc = htonl(BOOTPARAM_WHOAMI); + args->arglen = htonl(sizeof(struct xdr_inaddr)); + send_tail = (char *)&args->xina; + + /* + * append encapsulated data (client IP address) + */ + if (xdr_inaddr_encode(&send_tail, myip)) + return -1; + + /* RPC: portmap/callit */ + d->myport = htons(--rpc_port); + d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */ + /* rpc_call will set d->destport */ + + len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT, + args, send_tail - (char *)args, + repl, sizeof(*repl)); + if (len < 8) { + printf("bootparamd: 'whoami' call failed\n"); + return -1; + } + + /* Save bootparam server address (from IP header). */ + rpc_fromaddr(repl, &bp_server_addr, &bp_server_port); + + /* + * Note that bp_server_port is now 111 due to the + * indirect call (using PMAPPROC_CALLIT), so get the + * actual port number from the reply data. + */ + bp_server_port = repl->port; + + RPC_PRINTF(("bp_whoami: server at %s:%d\n", + inet_ntoa(bp_server_addr), ntohs(bp_server_port))); + + /* We have just done a portmap call, so cache the portnum. */ + rpc_pmap_putcache(bp_server_addr, + BOOTPARAM_PROG, + BOOTPARAM_VERS, + (int)ntohs(bp_server_port)); + + /* + * Parse the encapsulated results from bootparam/whoami + */ + x = ntohl(repl->encap_len); + if (len < x) { + printf("bp_whoami: short reply, %d < %d\n", len, x); + return -1; + } + recv_head = (char *)repl->capsule; + + /* client name */ + hostnamelen = MAXHOSTNAMELEN-1; + if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) { + RPC_PRINTF(("bp_whoami: bad hostname\n")); + return -1; + } + + /* domain name */ + domainnamelen = MAXHOSTNAMELEN-1; + if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) { + RPC_PRINTF(("bp_whoami: bad domainname\n")); + return -1; + } + + /* gateway address */ + if (xdr_inaddr_decode(&recv_head, &gateip)) { + RPC_PRINTF(("bp_whoami: bad gateway\n")); + return -1; + } + + /* success */ + return 0; +} + + +/* + * RPC: bootparam/getfile + * Given client name and file "key", get: + * server name + * server IP address + * server pathname + */ +int +bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname) +{ + struct { + n_long h[RPC_HEADER_WORDS]; + n_long d[64]; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + n_long d[128]; + } rdata; + char serv_name[FNAME_SIZE]; + char *send_tail, *recv_head; + /* misc... */ + struct iodesc *d; + int sn_len, path_len, rlen; + + if (!(d = socktodesc(sockfd))) { + RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd)); + return -1; + } + + send_tail = (char *)sdata.d; + recv_head = (char *)rdata.d; + + /* + * Build request message. + */ + + /* client name (hostname) */ + if (xdr_string_encode(&send_tail, hostname, hostnamelen)) { + RPC_PRINTF(("bp_getfile: bad client\n")); + return -1; + } + + /* key name (root or swap) */ + if (xdr_string_encode(&send_tail, key, strlen(key))) { + RPC_PRINTF(("bp_getfile: bad key\n")); + return -1; + } + + /* RPC: bootparam/getfile */ + d->myport = htons(--rpc_port); + d->destip = bp_server_addr; + /* rpc_call will set d->destport */ + + rlen = rpc_call(d, + BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE, + sdata.d, send_tail - (char *)sdata.d, + rdata.d, sizeof(rdata.d)); + if (rlen < 4) { + RPC_PRINTF(("bp_getfile: short reply\n")); + errno = EBADRPC; + return -1; + } + recv_head = (char *)rdata.d; + + /* + * Parse result message. + */ + + /* server name */ + sn_len = FNAME_SIZE-1; + if (xdr_string_decode(&recv_head, serv_name, &sn_len)) { + RPC_PRINTF(("bp_getfile: bad server name\n")); + return -1; + } + + /* server IP address (mountd/NFS) */ + if (xdr_inaddr_decode(&recv_head, serv_addr)) { + RPC_PRINTF(("bp_getfile: bad server addr\n")); + return -1; + } + + /* server pathname */ + path_len = MAXPATHLEN - 1; + if (xdr_string_decode(&recv_head, pathname, &path_len)) { + RPC_PRINTF(("bp_getfile: bad server path\n")); + return -1; + } + + /* success */ + return 0; +} + + +/* + * eXternal Data Representation routines. + * (but with non-standard args...) + */ + + +int +xdr_string_encode(char **pkt, char *str, int len) +{ + u_int32_t *lenp; + char *datap; + int padlen = (len + 3) & ~3; /* padded length */ + + /* The data will be int aligned. */ + lenp = (u_int32_t *)*pkt; + *pkt += sizeof(*lenp); + *lenp = htonl(len); + + datap = *pkt; + *pkt += padlen; + (void)memcpy(datap, str, len); + + return 0; +} + +/* len_p: bufsize - 1 */ +int +xdr_string_decode(char **pkt, char *str, int *len_p) +{ + u_int32_t *lenp; + char *datap; + int slen; /* string length */ + int plen; /* padded length */ + + /* The data will be int aligned. */ + lenp = (u_int32_t *)*pkt; + *pkt += sizeof(*lenp); + slen = ntohl(*lenp); + plen = (slen + 3) & ~3; + + if (slen > *len_p) + slen = *len_p; + datap = *pkt; + *pkt += plen; + (void)memcpy(str, datap, slen); + + str[slen] = '\0'; + *len_p = slen; + + return 0; +} + + +/* ia: network order */ +int +xdr_inaddr_encode(char **pkt, struct in_addr ia) +{ + struct xdr_inaddr *xi; + u_char *cp; + int32_t *ip; + union { + n_long l; /* network order */ + u_char c[4]; + } uia; + + /* The data will be int aligned. */ + xi = (struct xdr_inaddr *)*pkt; + *pkt += sizeof(*xi); + xi->atype = htonl(1); + uia.l = ia.s_addr; + cp = uia.c; + ip = xi->addr; + /* + * Note: the htonl() calls below DO NOT + * imply that uia.l is in host order. + * In fact this needs it in net order. + */ + *ip++ = htonl((unsigned int)*cp++); + *ip++ = htonl((unsigned int)*cp++); + *ip++ = htonl((unsigned int)*cp++); + *ip++ = htonl((unsigned int)*cp++); + + return 0; +} + +/* ia: network order */ +int +xdr_inaddr_decode(char **pkt, struct in_addr *ia) +{ + struct xdr_inaddr *xi; + u_char *cp; + int32_t *ip; + union { + n_long l; /* network order */ + u_char c[4]; + } uia; + + /* The data will be int aligned. */ + xi = (struct xdr_inaddr *)*pkt; + *pkt += sizeof(*xi); + if (xi->atype != htonl(1)) { + RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n", + ntohl(xi->atype))); + return -1; + } + + cp = uia.c; + ip = xi->addr; + /* + * Note: the ntohl() calls below DO NOT + * imply that uia.l is in host order. + * In fact this needs it in net order. + */ + *cp++ = ntohl(*ip++); + *cp++ = ntohl(*ip++); + *cp++ = ntohl(*ip++); + *cp++ = ntohl(*ip++); + ia->s_addr = uia.l; + + return 0; +} diff --git a/sys/lib/libsa/bootparam.h b/sys/lib/libsa/bootparam.h new file mode 100644 index 000000000..b60a2c726 --- /dev/null +++ b/sys/lib/libsa/bootparam.h @@ -0,0 +1,4 @@ +/* $NetBSD: bootparam.h,v 1.4 2007/11/24 13:20:54 isaki Exp $ */ + +int bp_whoami(int); +int bp_getfile(int, char *, struct in_addr *, char *); diff --git a/sys/lib/libsa/byteorder.c b/sys/lib/libsa/byteorder.c new file mode 100644 index 000000000..204070da3 --- /dev/null +++ b/sys/lib/libsa/byteorder.c @@ -0,0 +1,209 @@ +/* $NetBSD: byteorder.c,v 1.3 2007/11/24 13:20:54 isaki Exp $ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "byteorder.h" + +typedef union { + uint16_t val; + uint8_t bytes[2]; +} un16; + +typedef union { + uint32_t val; + uint8_t bytes[4]; +} un32; + +typedef union { + uint64_t val; + uint32_t words[2]; +} un64; + +/* 16-bit */ + +uint16_t +sa_htobe16(uint16_t val) +{ + un16 un; + + un.bytes[1] = val & 0xff; + un.bytes[0] = (val >> 8) & 0xff; + + return un.val; +} + +uint16_t +sa_htole16(uint16_t val) +{ + un16 un; + + un.bytes[0] = val & 0xff; + un.bytes[1] = (val >> 8) & 0xff; + + return un.val; +} + +uint16_t +sa_be16toh(uint16_t val) +{ + un16 un; + + un.val = val; + + return ((un.bytes[0] << 8) | + un.bytes[1]); +} + +uint16_t +sa_le16toh(uint16_t val) +{ + un16 un; + + un.val = val; + + return ((un.bytes[1] << 8) | + un.bytes[0]); +} + +/* 32-bit */ + +uint32_t +sa_htobe32(uint32_t val) +{ + un32 un; + + un.bytes[3] = val & 0xff; + un.bytes[2] = (val >> 8) & 0xff; + un.bytes[1] = (val >> 16) & 0xff; + un.bytes[0] = (val >> 24) & 0xff; + + return un.val; +} + +uint32_t +sa_htole32(uint32_t val) +{ + un32 un; + + un.bytes[0] = val & 0xff; + un.bytes[1] = (val >> 8) & 0xff; + un.bytes[2] = (val >> 16) & 0xff; + un.bytes[3] = (val >> 24) & 0xff; + + return un.val; +} + +uint32_t +sa_be32toh(uint32_t val) +{ + un32 un; + + un.val = val; + + return ((un.bytes[0] << 24) | + (un.bytes[1] << 16) | + (un.bytes[2] << 8) | + un.bytes[3]); +} + +uint32_t +sa_le32toh(uint32_t val) +{ + un32 un; + + un.val = val; + + return ((un.bytes[3] << 24) | + (un.bytes[2] << 16) | + (un.bytes[1] << 8) | + un.bytes[0]); +} + +/* 64-bit */ + +uint64_t +sa_htobe64(uint64_t val) +{ + un64 un; + + un.words[BE64_HI] = sa_htobe32(val >> 32); + un.words[BE64_LO] = sa_htobe32(val & 0xffffffffU); + + return un.val; +} + +uint64_t +sa_htole64(uint64_t val) +{ + un64 un; + + un.words[LE64_HI] = sa_htole32(val >> 32); + un.words[LE64_LO] = sa_htole32(val & 0xffffffffU); + + return un.val; +} + +uint64_t +sa_be64toh(uint64_t val) +{ + un64 un; + uint64_t rv; + + un.val = val; + un.words[BE64_HI] = sa_be32toh(un.words[BE64_HI]); + un.words[BE64_LO] = sa_be32toh(un.words[BE64_LO]); + + rv = (((uint64_t)un.words[BE64_HI]) << 32) | + un.words[BE64_LO]; + + return rv; +} + +uint64_t +sa_le64toh(uint64_t val) +{ + un64 un; + uint64_t rv; + + un.val = val; + un.words[LE64_HI] = sa_le32toh(un.words[LE64_HI]); + un.words[LE64_LO] = sa_le32toh(un.words[LE64_LO]); + + rv = (((uint64_t)un.words[LE64_HI]) << 32) | + un.words[LE64_LO]; + + return rv; +} diff --git a/sys/lib/libsa/byteorder.h b/sys/lib/libsa/byteorder.h new file mode 100644 index 000000000..ce040b80f --- /dev/null +++ b/sys/lib/libsa/byteorder.h @@ -0,0 +1,70 @@ +/* $NetBSD: byteorder.h,v 1.3 2001/10/31 20:22:22 thorpej Exp $ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LIBSA_BYTEORDER_H_ +#define _LIBSA_BYTEORDER_H_ + +#ifdef _STANDALONE +#include +#else +#include +#endif + +uint16_t sa_htobe16(uint16_t); +uint16_t sa_htole16(uint16_t); +uint16_t sa_be16toh(uint16_t); +uint16_t sa_le16toh(uint16_t); + +uint32_t sa_htobe32(uint32_t); +uint32_t sa_htole32(uint32_t); +uint32_t sa_be32toh(uint32_t); +uint32_t sa_le32toh(uint32_t); + +uint64_t sa_htobe64(uint64_t); +uint64_t sa_htole64(uint64_t); +uint64_t sa_be64toh(uint64_t); +uint64_t sa_le64toh(uint64_t); + +/* Order of the words in a big-endian 64-bit word. */ +#define BE64_HI 0 +#define BE64_LO 1 + +/* Order of the words in a little-endian 64-bit word. */ +#define LE64_HI 1 +#define LE64_LO 0 + +#endif /* _LIBSA_BYTEORDER_H_ */ diff --git a/sys/lib/libsa/cd9660.c b/sys/lib/libsa/cd9660.c new file mode 100644 index 000000000..fa1418042 --- /dev/null +++ b/sys/lib/libsa/cd9660.c @@ -0,0 +1,407 @@ +/* $NetBSD: cd9660.c,v 1.28 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Stand-alone ISO9660 file reading package. + * + * Note: This doesn't support Rock Ridge extensions, extended attributes, + * blocksizes other than 2048 bytes, multi-extent files, etc. + */ +#include +#ifdef _STANDALONE +#include +#else +#include +#endif +#include + +#include "stand.h" +#include "cd9660.h" + +/* + * XXX Does not currently implement: + * XXX + * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?) + * XXX LIBSA_FS_SINGLECOMPONENT + */ + +struct file { + off_t off; /* Current offset within file */ + daddr_t bno; /* Starting block number */ + off_t size; /* Size of file */ +}; + +struct ptable_ent { + char namlen [ISODCL( 1, 1)]; /* 711 */ + char extlen [ISODCL( 2, 2)]; /* 711 */ + char block [ISODCL( 3, 6)]; /* 732 */ + char parent [ISODCL( 7, 8)]; /* 722 */ + char name [1]; +}; +#define PTFIXSZ 8 +#define PTSIZE(pp) roundup(PTFIXSZ + isonum_711((pp)->namlen), 2) + +#define cdb2devb(bno) ((bno) * ISO_DEFAULT_BLOCK_SIZE / DEV_BSIZE) + +static int pnmatch(const char *, struct ptable_ent *); +static int dirmatch(const char *, struct iso_directory_record *); + +static int +pnmatch(const char *path, struct ptable_ent *pp) +{ + char *cp; + int i; + + cp = pp->name; + for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) { + if (toupper(*path) == *cp) + continue; + return 0; + } + if (*path != '/') + return 0; + return 1; +} + +static int +dirmatch(const char *path, struct iso_directory_record *dp) +{ + char *cp; + int i; + + /* This needs to be a regular file */ + if (dp->flags[0] & 6) + return 0; + + cp = dp->name; + for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) { + if (!*path) + break; + if (toupper(*path) == *cp) + continue; + return 0; + } + if (*path) + return 0; + /* + * Allow stripping of trailing dots and the version number. + * Note that this will find the first instead of the last version + * of a file. + */ + if (i >= 0 && (*cp == ';' || *cp == '.')) { + /* This is to prevent matching of numeric extensions */ + if (*cp == '.' && cp[1] != ';') + return 0; + while (--i >= 0) + if (*++cp != ';' && (*cp < '0' || *cp > '9')) + return 0; + } + return 1; +} + +__compactcall int +cd9660_open(const char *path, struct open_file *f) +{ + struct file *fp = 0; + void *buf; + struct iso_primary_descriptor *vd; + size_t buf_size, nread, psize, dsize; + daddr_t bno; + int parent, ent; + struct ptable_ent *pp; + struct iso_directory_record *dp = 0; + int rc; + + /* First find the volume descriptor */ + buf_size = ISO_DEFAULT_BLOCK_SIZE; + buf = alloc(buf_size); + vd = buf; + for (bno = 16;; bno++) { +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), + ISO_DEFAULT_BLOCK_SIZE, buf, &nread); + if (rc) + goto out; + if (nread != ISO_DEFAULT_BLOCK_SIZE) { + rc = EIO; + goto out; + } + rc = EINVAL; + if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) + goto out; + if (isonum_711(vd->type) == ISO_VD_END) + goto out; + if (isonum_711(vd->type) == ISO_VD_PRIMARY) + break; + } + if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) + goto out; + + /* Now get the path table and lookup the directory of the file */ + bno = isonum_732(vd->type_m_path_table); + psize = isonum_733(vd->path_table_size); + + if (psize > ISO_DEFAULT_BLOCK_SIZE) { + dealloc(buf, ISO_DEFAULT_BLOCK_SIZE); + buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE)); + } + +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), + buf_size, buf, &nread); + if (rc) + goto out; + if (nread != buf_size) { + rc = EIO; + goto out; + } + + parent = 1; + pp = (struct ptable_ent *)buf; + ent = 1; + bno = isonum_732(pp->block) + isonum_711(pp->extlen); + + rc = ENOENT; + + while (*path) { + /* + * Remove extra separators + */ + while (*path == '/') + path++; + + if ((char *)pp >= (char *)buf + psize) + break; + if (isonum_722(pp->parent) != parent) + break; + if (!pnmatch(path, pp)) { + pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); + ent++; + continue; + } + path += isonum_711(pp->namlen) + 1; + parent = ent; + bno = isonum_732(pp->block) + isonum_711(pp->extlen); + while ((char *)pp < (char *)buf + psize) { + if (isonum_722(pp->parent) == parent) + break; + pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); + ent++; + } + } + + /* + * Now bno has the start of the directory that supposedly + * contains the file + */ + bno--; + dsize = 1; /* Something stupid, but > 0 XXX */ + for (psize = 0; psize < dsize;) { + if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) { + bno++; +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + cdb2devb(bno), + ISO_DEFAULT_BLOCK_SIZE, + buf, &nread); + if (rc) + goto out; + if (nread != ISO_DEFAULT_BLOCK_SIZE) { + rc = EIO; + goto out; + } + dp = (struct iso_directory_record *)buf; + } + if (!isonum_711(dp->length)) { + if ((void *)dp == buf) + psize += ISO_DEFAULT_BLOCK_SIZE; + else + psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE); + continue; + } + if (dsize == 1) + dsize = isonum_733(dp->size); + if (dirmatch(path, dp)) + break; + psize += isonum_711(dp->length); + dp = (struct iso_directory_record *) + ((char *)dp + isonum_711(dp->length)); + } + + if (psize >= dsize) { + rc = ENOENT; + goto out; + } + + /* allocate file system specific data structure */ + fp = alloc(sizeof(struct file)); + memset(fp, 0, sizeof(struct file)); + f->f_fsdata = (void *)fp; + + fp->off = 0; + fp->bno = isonum_733(dp->extent); + fp->size = isonum_733(dp->size); + dealloc(buf, buf_size); + fsmod = "cd9660"; + + return 0; + +out: + if (fp) + dealloc(fp, sizeof(struct file)); + dealloc(buf, buf_size); + + return rc; +} + +#if !defined(LIBSA_NO_FS_CLOSE) +__compactcall int +cd9660_close(struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + + f->f_fsdata = 0; + dealloc(fp, sizeof *fp); + + return 0; +} +#endif /* !defined(LIBSA_NO_FS_CLOSE) */ + +__compactcall int +cd9660_read(struct open_file *f, void *start, size_t size, size_t *resid) +{ + struct file *fp = (struct file *)f->f_fsdata; + int rc = 0; + daddr_t bno; + char buf[ISO_DEFAULT_BLOCK_SIZE]; + char *dp; + size_t nread, off; + + while (size) { + if (fp->off < 0 || fp->off >= fp->size) + break; + bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno; + if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1) + || size < ISO_DEFAULT_BLOCK_SIZE) + dp = buf; + else + dp = start; +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), + ISO_DEFAULT_BLOCK_SIZE, dp, &nread); + if (rc) + return rc; + if (nread != ISO_DEFAULT_BLOCK_SIZE) + return EIO; + if (dp == buf) { + off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1); + if (nread > off + size) + nread = off + size; + nread -= off; + memcpy(start, buf + off, nread); + start = (char *)start + nread; + fp->off += nread; + size -= nread; + } else { + start = (char *)start + ISO_DEFAULT_BLOCK_SIZE; + fp->off += ISO_DEFAULT_BLOCK_SIZE; + size -= ISO_DEFAULT_BLOCK_SIZE; + } + } + if(fp->off > fp->size) + size += fp->off - fp->size; + if (resid) + *resid = size; + return rc; +} + +#if !defined(LIBSA_NO_FS_WRITE) +__compactcall int +cd9660_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !defined(LIBSA_NO_FS_WRITE) */ + +#if !defined(LIBSA_NO_FS_SEEK) +__compactcall off_t +cd9660_seek(struct open_file *f, off_t offset, int where) +{ + struct file *fp = (struct file *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + fp->off = offset; + break; + case SEEK_CUR: + fp->off += offset; + break; + case SEEK_END: + fp->off = fp->size - offset; + break; + default: + return -1; + } + return fp->off; +} +#endif /* !defined(LIBSA_NO_FS_SEEK) */ + +__compactcall int +cd9660_stat(struct open_file *f, struct stat *sb) +{ + struct file *fp = (struct file *)f->f_fsdata; + + /* only importatn stuff */ + sb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + sb->st_uid = sb->st_gid = 0; + sb->st_size = fp->size; + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +cd9660_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by cd9660\n"); + return; +} +#endif diff --git a/sys/lib/libsa/cd9660.h b/sys/lib/libsa/cd9660.h new file mode 100644 index 000000000..74f740fe8 --- /dev/null +++ b/sys/lib/libsa/cd9660.h @@ -0,0 +1,34 @@ +/* $NetBSD: cd9660.h,v 1.3 2005/12/11 12:24:46 christos Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +FS_DEF(cd9660); diff --git a/sys/lib/libsa/checkpasswd.c b/sys/lib/libsa/checkpasswd.c new file mode 100644 index 000000000..df7c28ac9 --- /dev/null +++ b/sys/lib/libsa/checkpasswd.c @@ -0,0 +1,131 @@ +/* $NetBSD: checkpasswd.c,v 1.9 2011/01/06 02:45:13 jakllsch Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)gets.c 8.1 (Berkeley) 6/11/93 + */ + +#ifdef _STANDALONE +#include +#else +#include +#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 + +char bootpasswd[16] = {'\0'}; /* into data segment! */ + +int +checkpasswd(void) +{ + + return check_password(bootpasswd); +} + +int +check_password(const char *password) +{ + int i; + char *passwd; + MD5_CTX md5ctx; + char pwdigest[16]; + + for (i = 0; i < 16; i++) + if (password[i]) + break; + if (i == 16) + return 1; /* no password set */ + + for (i = 0; i < 3; i++) { + passwd = getpass("Password: "); + MD5Init(&md5ctx); + MD5Update(&md5ctx, passwd, strlen(passwd)); + MD5Final(pwdigest, &md5ctx); + if (memcmp(pwdigest, password, 16) == 0) + return 1; + } + + /* failed */ + return 0; +} diff --git a/sys/lib/libsa/close.c b/sys/lib/libsa/close.c new file mode 100644 index 000000000..45d0a579b --- /dev/null +++ b/sys/lib/libsa/close.c @@ -0,0 +1,103 @@ +/* $NetBSD: close.c,v 1.14 2007/12/02 04:59:25 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)close.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +int +#ifndef __INTERNAL_LIBSA_CREAD +close(int fd) +#else +oclose(int fd) +#endif +{ + struct open_file *f = &files[fd]; + int err1 = 0, err2 = 0; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + return -1; + } +#endif +#if !defined(LIBSA_NO_RAW_ACCESS) + if (!(f->f_flags & F_RAW)) +#endif +#if !defined(LIBSA_SINGLE_FILESYSTEM) + if (f->f_ops != NULL) +#endif + err1 = FS_CLOSE(f->f_ops)(f); + if (!(f->f_flags & F_NODEV)) +#if !defined(LIBSA_SINGLE_DEVICE) + if (f->f_dev != NULL) +#endif + err2 = DEV_CLOSE(f->f_dev)(f); + f->f_flags = 0; + if (err1) { + errno = err1; + return -1; + } + if (err2) { + errno = err2; + return -1; + } + return 0; +} diff --git a/sys/lib/libsa/closeall.c b/sys/lib/libsa/closeall.c new file mode 100644 index 000000000..a8f8121de --- /dev/null +++ b/sys/lib/libsa/closeall.c @@ -0,0 +1,73 @@ +/* $NetBSD: closeall.c,v 1.5 2007/11/24 13:20:54 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)close.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +void +closeall(void) +{ + int i; + + for (i = 0; i < SOPEN_MAX; i++) + if (files[i].f_flags != 0) + (void)close(i); +} diff --git a/sys/lib/libsa/cread.c b/sys/lib/libsa/cread.c new file mode 100644 index 000000000..808690cef --- /dev/null +++ b/sys/lib/libsa/cread.c @@ -0,0 +1,493 @@ +/* $NetBSD: cread.c,v 1.23 2009/03/25 18:41:06 tls Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Support for compressed bootfiles (only read) + * + * - replaces open(), close(), read(), lseek(). + * - original libsa open(), close(), read(), lseek() are called + * as oopen(), oclose(), oread() resp. olseek(). + * - compression parts stripped from zlib:gzio.c + */ + +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-1996 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "stand.h" +#ifdef _STANDALONE +#include +#include +#else +#include +#include +#endif + +#define EOF (-1) /* needed by compression code */ + +#ifdef SAVE_MEMORY +#define Z_BUFSIZE 1024 +#else +#define Z_BUFSIZE 4096 +#endif + +static const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +static struct sd { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + int fd; + unsigned char *inbuf; /* input buffer */ + unsigned long crc; /* crc32 of uncompressed data */ + int compressed; /* 1 if input file is a .gz file */ +} *ss[SOPEN_MAX]; + +static int get_byte(struct sd *); +static unsigned long getLong(struct sd *); +static void check_header(struct sd *); + +/* XXX - find suitable header file for these: */ +void *zcalloc(void *, unsigned int, unsigned int); +void zcfree(void *, void *); +void zmemcpy(unsigned char *, unsigned char *, unsigned int); + +/* + * The libkern version of this function uses an 8K set of tables. + * This is the double-loop version of LE CRC32 from if_ethersubr, + * lightly modified -- it is 200 bytes smaller than the version using + * a 4-bit table and at least 8K smaller than the libkern version. + */ +#ifndef ETHER_CRC_POLY_LE +#define ETHER_CRC_POLY_LE 0xedb88320 +#endif +uint32_t +crc32(uint32_t crc, const uint8_t *const buf, size_t len) +{ + uint32_t c, carry; + size_t i, j; + + crc = 0xffffffffU ^ crc; + for (i = 0; i < len; i++) { + c = buf[i]; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01); + crc >>= 1; + c >>= 1; + if (carry) { + crc = (crc ^ ETHER_CRC_POLY_LE); + } + } + } + return (crc ^ 0xffffffffU); +} + +/* + * compression utilities + */ + +void * +zcalloc(void *opaque, unsigned int items, unsigned int size) +{ + + return alloc(items * size); +} + +void +zcfree(void *opaque, void *ptr) +{ + + dealloc(ptr, 0); /* XXX works only with modified allocator */ +} + +void +zmemcpy(unsigned char *dest, unsigned char *source, unsigned int len) +{ + + memcpy(dest, source, len); +} + +static int +get_byte(struct sd *s) +{ + if (s->z_eof) + return EOF; + + if (s->stream.avail_in == 0) { + int got; + + errno = 0; + got = oread(s->fd, s->inbuf, Z_BUFSIZE); + if (got <= 0) { + s->z_eof = 1; + if (errno) + s->z_err = Z_ERRNO; + return EOF; + } + s->stream.avail_in = got; + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +static unsigned long +getLong(struct sd *s) +{ + unsigned long x; + int c; + + x = (unsigned long)get_byte(s); + x += ((unsigned long)get_byte(s)) << 8; + x += ((unsigned long)get_byte(s)) << 16; + c = get_byte(s); + if (c == EOF) + s->z_err = Z_DATA_ERROR; + x += ((unsigned long)c) << 24; + return x; +} + +static void +check_header(struct sd *s) +{ + int method; /* method byte */ + int flags; /* flags byte */ + unsigned int len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c == gz_magic[len]) + continue; + if ((c == EOF) && (len == 0)) { + /* + * We must not change s->compressed if we are at EOF; + * we may have come to the end of a gzipped file and be + * check to see if another gzipped file is concatenated + * to this one. If one isn't, we still need to be able + * to lseek on this file as a compressed file. + */ + return; + } + s->compressed = 0; + if (c != EOF) { + s->stream.avail_in++; + s->stream.next_in--; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + s->compressed = 1; + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) + (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { + /* skip the extra field */ + len = (unsigned int)get_byte(s); + len += ((unsigned int)get_byte(s)) << 8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) + /*void*/; + } + if ((flags & ORIG_NAME) != 0) { + /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) + /*void*/; + } + if ((flags & COMMENT) != 0) { + /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) + /*void*/; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) + (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + +/* + * new open(), close(), read(), lseek() + */ + +int +open(const char *fname, int mode) +{ + int fd; + struct sd *s = 0; + + if (((fd = oopen(fname, mode)) == -1) || (mode != 0)) + /* compression only for read */ + return fd; + + ss[fd] = s = alloc(sizeof(struct sd)); + if (s == 0) + goto errout; + (void)memset(s, 0, sizeof(struct sd)); + + if (inflateInit2(&(s->stream), -15) != Z_OK) + goto errout; + + s->stream.next_in = s->inbuf = (unsigned char *)alloc(Z_BUFSIZE); + if (s->inbuf == 0) { + inflateEnd(&(s->stream)); + goto errout; + } + + s->fd = fd; + check_header(s); /* skip the .gz header */ + return fd; + +errout: + if (s != 0) + dealloc(s, sizeof(struct sd)); + oclose(fd); + return -1; +} + +int +close(int fd) +{ + struct open_file *f; + struct sd *s; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX) { + errno = EBADF; + return -1; + } +#endif + f = &files[fd]; + + if ((f->f_flags & F_READ) == 0) + return oclose(fd); + + s = ss[fd]; + + inflateEnd(&(s->stream)); + + dealloc(s->inbuf, Z_BUFSIZE); + dealloc(s, sizeof(struct sd)); + + return oclose(fd); +} + +ssize_t +read(int fd, void *buf, size_t len) +{ + struct sd *s; + unsigned char *start = buf; /* starting point for crc computation */ + + s = ss[fd]; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) + return -1; + if (s->z_err == Z_STREAM_END) + return 0; /* EOF */ + + s->stream.next_out = buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->compressed == 0) { + /* Copy first the lookahead bytes: */ + unsigned int n = s->stream.avail_in; + if (n > s->stream.avail_out) + n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, + s->stream.next_in, n); + s->stream.next_out += n; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + int got; + got = oread(s->fd, s->stream.next_out, + s->stream.avail_out); + if (got == -1) + return got; + s->stream.avail_out -= got; + } + return (int)(len - s->stream.avail_out); + } + + if (s->stream.avail_in == 0 && !s->z_eof) { + int got; + errno = 0; + got = oread(fd, s->inbuf, Z_BUFSIZE); + if (got <= 0) { + s->z_eof = 1; + if (errno) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.avail_in = got; + s->stream.next_in = s->inbuf; + } + + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (unsigned int) + (s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc || + getLong(s) != s->stream.total_out) { + + s->z_err = Z_DATA_ERROR; + } else { + /* Check for concatenated .gz files: */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) + break; + } + + s->crc = crc32(s->crc, start, + (unsigned int)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + +off_t +lseek(int fd, off_t offset, int where) +{ + struct open_file *f; + struct sd *s; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX) { + errno = EBADF; + return -1; + } +#endif + f = &files[fd]; + + if ((f->f_flags & F_READ) == 0) + return olseek(fd, offset, where); + + s = ss[fd]; + + if(s->compressed == 0) { + off_t res = olseek(fd, offset, where); + if (res != (off_t)-1) { + /* make sure the lookahead buffer is invalid */ + s->stream.avail_in = 0; + } + return res; + } + + switch(where) { + case SEEK_CUR: + offset += s->stream.total_out; + case SEEK_SET: + /* if seek backwards, simply start from the beginning */ + if (offset < s->stream.total_out) { + off_t res; + void *sav_inbuf; + + res = olseek(fd, 0, SEEK_SET); + if(res == (off_t)-1) + return res; + /* ??? perhaps fallback to close / open */ + + inflateEnd(&(s->stream)); + + sav_inbuf = s->inbuf; /* don't allocate again */ + (void)memset(s, 0, sizeof(struct sd)); + /* this resets total_out to 0! */ + + inflateInit2(&(s->stream), -15); + s->stream.next_in = s->inbuf = sav_inbuf; + + s->fd = fd; + check_header(s); /* skip the .gz header */ + } + + /* to seek forwards, throw away data */ + if (offset > s->stream.total_out) { + off_t toskip = offset - s->stream.total_out; + + while (toskip > 0) { +#define DUMMYBUFSIZE 256 + char dummybuf[DUMMYBUFSIZE]; + off_t len = toskip; + + if (len > DUMMYBUFSIZE) + len = DUMMYBUFSIZE; + if (read(fd, dummybuf, len) != len) { + errno = EOFFSET; + return (off_t)-1; + } + toskip -= len; + } + } +#ifdef DEBUG + if (offset != s->stream.total_out) + panic("lseek compressed"); +#endif + return offset; + case SEEK_END: + errno = EOFFSET; + break; + default: + errno = EINVAL; + break; + } + + return (off_t)-1; +} diff --git a/sys/lib/libsa/dev.c b/sys/lib/libsa/dev.c new file mode 100644 index 000000000..793aecaef --- /dev/null +++ b/sys/lib/libsa/dev.c @@ -0,0 +1,57 @@ +/* $NetBSD: dev.c,v 1.8 2007/11/24 13:20:54 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dev.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +#include "stand.h" + +int +nodev(void) +{ + + return ENXIO; +} + +void +nullsys(void) +{ +} + +/* ARGSUSED */ +int +noioctl(struct open_file *f, u_long cmd, void *data) +{ + + return EINVAL; +} diff --git a/sys/lib/libsa/dev_net.c b/sys/lib/libsa/dev_net.c new file mode 100644 index 000000000..a15c000d1 --- /dev/null +++ b/sys/lib/libsa/dev_net.c @@ -0,0 +1,284 @@ +/* $NetBSD: dev_net.c,v 1.26 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This module implements a "raw device" interface suitable for + * use by the stand-alone I/O library NFS code. This interface + * does not support any "block" access, and exists only for the + * purpose of initializing the network interface, getting boot + * parameters, and performing the NFS mount. + * + * At open time, this does: + * + * find interface - netif_open() + * RARP for IP address - rarp_getipaddress() + * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) + * RPC/mountd - nfs_mount(sock, ip, path) + * + * the root file handle from mountd is saved in a global + * for use by the NFS open code (NFS/lookup). + */ + +#include +#include +#include +#include +#include + +#include + +#include "stand.h" +#include "net.h" +#include "netif.h" +#include "nfs.h" +#include "bootparam.h" +#include "dev_net.h" +#ifdef SUPPORT_BOOTP +#include "bootp.h" +#endif + +extern int nfs_root_node[]; /* XXX - get from nfs_mount() */ + +static int netdev_sock = -1; +static int netdev_opens; + +static int net_getparams(int); + +/* + * Called by devopen after it sets f->f_dev to our devsw entry. + * This opens the low-level device and sets f->f_devdata. + * This is declared with variable arguments... + */ +int +net_open(struct open_file *f, ...) +{ + va_list ap; + char *devname; /* Device part of file name (or NULL). */ + int error = 0; + + va_start(ap, f); + devname = va_arg(ap, char *); + va_end(ap); + +#ifdef NETIF_DEBUG + if (debug) + printf("%s\n", devname); +#endif + + /* On first open, do netif open, mount, etc. */ + if (netdev_opens == 0) { + /* Find network interface. */ + if (netdev_sock < 0) { + netdev_sock = netif_open(devname); + if (netdev_sock < 0) { + printf("netif_open() failed\n"); + return ENXIO; + } +#ifdef NETIF_DEBUG + if (debug) + printf("netif_open() succeeded\n"); +#endif + } + if (rootip.s_addr == 0) { + /* Get root IP address, and path, etc. */ + error = net_getparams(netdev_sock); + if (error) { + /* getparams makes its own noise */ + goto fail; + } + /* Get the NFS file handle (mountd). */ + error = nfs_mount(netdev_sock, rootip, rootpath); + if (error) { + printf("NFS mount error=%d\n", errno); + rootip.s_addr = 0; + fail: + netif_close(netdev_sock); + netdev_sock = -1; + return error; + } +#ifdef NETIF_DEBUG + if (debug) + printf("NFS mount succeeded\n"); +#endif + } + } + netdev_opens++; + f->f_devdata = nfs_root_node; + return error; +} + +int +net_close(struct open_file *f) +{ + +#ifdef NETIF_DEBUG + if (debug) + printf("net_close: opens=%d\n", netdev_opens); +#endif + + /* On last close, do netif close, etc. */ + f->f_devdata = NULL; + /* Extra close call? */ + if (netdev_opens <= 0) + return 0; + netdev_opens--; + /* Not last close? */ + if (netdev_opens > 0) + return 0; + rootip.s_addr = 0; + if (netdev_sock >= 0) { +#ifdef NETIF_DEBUG + if (debug) + printf("net_close: calling netif_close()\n"); +#endif + netif_close(netdev_sock); + netdev_sock = -1; + } + return 0; +} + +int +net_ioctl(struct open_file *f, u_long cmd, void *data) +{ + + return EIO; +} + +int +net_strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, + size_t *rsize) +{ + + return EIO; +} + + +/* + * Get info for NFS boot: our IP address, our hostname, + * server IP address, and our root path on the server. + * There are two ways to do this: The old, Sun way, + * and the more modern, BOOTP way. (RFC951, RFC1048) + * + * The default is to use the Sun bootparams RPC + * (because that is what the kernel will do). + * MD code can make try_bootp initialied data, + * which will override this common definition. + */ +#ifdef SUPPORT_BOOTP +int try_bootp; +#endif + +static int +net_getparams(int sock) +{ + char buf[MAXHOSTNAMELEN]; + n_long smask; + +#ifdef SUPPORT_BOOTP + /* + * Try to get boot info using BOOTP. If we succeed, then + * the server IP address, gateway, and root path will all + * be initialized. If any remain uninitialized, we will + * use RARP and RPC/bootparam (the Sun way) to get them. + */ + if (try_bootp) + bootp(sock); + if (myip.s_addr != 0) + return 0; +#ifdef NETIF_DEBUG + if (debug) + printf("BOOTP failed, trying RARP/RPC...\n"); +#endif +#endif + + /* + * Use RARP to get our IP address. This also sets our + * netmask to the "natural" default for our address. + */ + if (rarp_getipaddress(sock)) { + printf("RARP failed\n"); + return EIO; + } +#ifdef NETIF_DEBUG + if (debug) + printf("client addr: %s\n", inet_ntoa(myip)); +#endif + + /* Get our hostname, server IP address, gateway. */ + if (bp_whoami(sock)) { + printf("bootparam/whoami RPC failed\n"); + return EIO; + } +#ifdef NETIF_DEBUG + if (debug) + printf("client name: %s\n", hostname); +#endif + + /* + * Ignore the gateway from whoami (unreliable). + * Use the "gateway" parameter instead. + */ + smask = 0; + gateip.s_addr = 0; + if (bp_getfile(sock, "gateway", &gateip, buf)) { + printf("nfs_open: gateway bootparam missing\n"); + } else { + /* Got it! Parse the netmask. */ + smask = inet_addr(buf); + } + if (smask) { + netmask = smask; +#ifdef NETIF_DEBUG + if (debug) + printf("subnet mask: %s\n", intoa(netmask)); +#endif + } +#ifdef NETIF_DEBUG + if (debug) + if (gateip.s_addr) + printf("net gateway: %s\n", inet_ntoa(gateip)); +#endif + + /* Get the root server and pathname. */ + if (bp_getfile(sock, "root", &rootip, rootpath)) { + printf("bootparam/getfile RPC failed\n"); + return EIO; + } + +#ifdef NETIF_DEBUG + if (debug) { + printf("server addr: %s\n", inet_ntoa(rootip)); + printf("server path: %s\n", rootpath); + } +#endif + + return 0; +} diff --git a/sys/lib/libsa/dev_net.h b/sys/lib/libsa/dev_net.h new file mode 100644 index 000000000..c4de3cce4 --- /dev/null +++ b/sys/lib/libsa/dev_net.h @@ -0,0 +1,10 @@ +/* $NetBSD: dev_net.h,v 1.6 2009/01/17 14:00:36 tsutsui Exp $ */ + +int net_open(struct open_file *, ...); +int net_close(struct open_file *); +int net_ioctl(struct open_file *, u_long, void *); +int net_strategy(void *, int , daddr_t , size_t, void *, size_t *); + +#ifdef SUPPORT_BOOTP +extern int try_bootp; +#endif diff --git a/sys/lib/libsa/disklabel.c b/sys/lib/libsa/disklabel.c new file mode 100644 index 000000000..f6aca5a7c --- /dev/null +++ b/sys/lib/libsa/disklabel.c @@ -0,0 +1,69 @@ +/* $NetBSD: disklabel.c,v 1.10 2007/11/24 13:20:54 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)disklabel.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include +#include "stand.h" + + +#if defined(LIBSA_NO_DISKLABEL_MSGS) +#define nolabel (char *)1 +#define corruptedlabel (char *)1 +#else +static char nolabel[] = "no disk label"; +static char corruptedlabel[] = "disk label corrupted"; +#endif + +char * +getdisklabel(const char *buf, struct disklabel *lp) +{ + const struct disklabel *dlp, *elp; + char *msg = NULL; + + elp = (const void *)(buf + DEV_BSIZE - sizeof(*dlp)); + for (dlp = (const void *)buf; dlp <= elp; + dlp = (const void *)((const char *)dlp + sizeof(long))) { + if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { + if (msg == NULL) + msg = nolabel; + } else if (dlp->d_npartitions > MAXPARTITIONS || + dkcksum(dlp) != 0) { + msg = corruptedlabel; + } else { + (void)memcpy(lp, dlp, sizeof *lp); + msg = NULL; + break; + } + } + return msg; +} diff --git a/sys/lib/libsa/dkcksum.c b/sys/lib/libsa/dkcksum.c new file mode 100644 index 000000000..3a96cc48b --- /dev/null +++ b/sys/lib/libsa/dkcksum.c @@ -0,0 +1,52 @@ +/* $NetBSD: dkcksum.c,v 1.5 2005/12/11 12:24:46 christos Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)disklabel.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include +#include "stand.h" + +/* + * Compute checksum for disk label. + */ +int +dkcksum(const struct disklabel *lp) +{ + const u_short *start, *end; + u_short sum = 0; + + start = (const void *)lp; + end = (const void *)&lp->d_partitions[lp->d_npartitions]; + while (start < end) + sum ^= *start++; + return sum; +} diff --git a/sys/lib/libsa/dosfs.c b/sys/lib/libsa/dosfs.c new file mode 100644 index 000000000..82ddfbdf9 --- /dev/null +++ b/sys/lib/libsa/dosfs.c @@ -0,0 +1,797 @@ +/* $NetBSD: dosfs.c,v 1.18 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* + * Copyright (c) 1996, 1998 Robert Nordier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Readonly filesystem for Microsoft FAT12/FAT16/FAT32 filesystems, + * also supports VFAT. + */ + +/* + * XXX DOES NOT SUPPORT: + * + * LIBSA_FS_SINGLECOMPONENT + */ + +#include + +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#include +#endif + +#include "stand.h" +#include "dosfs.h" + +#define SECSIZ 512 /* sector size */ +#define SSHIFT 9 /* SECSIZ shift */ +#define DEPSEC 16 /* directory entries per sector */ +#define DSHIFT 4 /* DEPSEC shift */ +#define LOCLUS 2 /* lowest cluster number */ + +typedef union { + struct direntry de; /* standard directory entry */ + struct winentry xde; /* extended directory entry */ +} DOS_DIR; + +typedef struct { + struct open_file *fd; /* file descriptor */ + u_char *buf; /* buffer */ + u_int bufsec; /* buffered sector */ + u_int links; /* active links to structure */ + u_int spc; /* sectors per cluster */ + u_int bsize; /* cluster size in bytes */ + u_int bshift; /* cluster conversion shift */ + u_int dirents; /* root directory entries */ + u_int spf; /* sectors per fat */ + u_int rdcl; /* root directory start cluster */ + u_int lsnfat; /* start of fat */ + u_int lsndir; /* start of root dir */ + u_int lsndta; /* start of data area */ + u_int fatsz; /* FAT entry size */ + u_int xclus; /* maximum cluster number */ +} DOS_FS; + +typedef struct { + DOS_FS *fs; /* associated filesystem */ + struct direntry de; /* directory entry */ + u_int offset; /* current offset */ + u_int c; /* last cluster read */ +} DOS_FILE; + +/* Initial portion of DOS boot sector */ +typedef struct { + u_char jmp[3]; /* usually 80x86 'jmp' opcode */ + u_char oem[8]; /* OEM name and version */ + struct byte_bpb710 bpb; /* BPB */ +} DOS_BS; + +/* Supply missing "." and ".." root directory entries */ +static const char *const dotstr[2] = {".", ".."}; +static const struct direntry dot[2] = { + {". ", " ", ATTR_DIRECTORY, + 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}}, + + {".. ", " ", ATTR_DIRECTORY, + 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}} +}; + +/* The usual conversion macros to avoid multiplication and division */ +#define bytsec(n) ((n) >> SSHIFT) +#define secbyt(s) ((s) << SSHIFT) +#define entsec(e) ((e) >> DSHIFT) +#define bytblk(fs, n) ((n) >> (fs)->bshift) +#define blkbyt(fs, b) ((b) << (fs)->bshift) +#define secblk(fs, s) ((s) >> ((fs)->bshift - SSHIFT)) +#define blksec(fs, b) ((b) << ((fs)->bshift - SSHIFT)) + +/* Convert cluster number to offset within filesystem */ +#define blkoff(fs, b) (secbyt((fs)->lsndta) + blkbyt(fs, (b) - LOCLUS)) + +/* Convert cluster number to logical sector number */ +#define blklsn(fs, b) ((fs)->lsndta + blksec(fs, (b) - LOCLUS)) + +/* Convert cluster number to offset within FAT */ +#define fatoff(sz, c) ((sz) == 12 ? (c) + ((c) >> 1) : \ + (sz) == 16 ? (c) << 1 : \ + (c) << 2) + +/* Does cluster number reference a valid data cluster? */ +#define okclus(fs, c) ((c) >= LOCLUS && (c) <= (fs)->xclus) + +/* Get start cluster from directory entry */ +#define stclus(sz, de) ((sz) != 32 ? (u_int)getushort((de)->deStartCluster) : \ + ((u_int)getushort((de)->deHighClust) << 16) | \ + (u_int)getushort((de)->deStartCluster)) + +static int dosunmount(DOS_FS *); +static int parsebs(DOS_FS *, DOS_BS *); +static int namede(DOS_FS *, const char *, const struct direntry **); +static int lookup(DOS_FS *, u_int, const char *, const struct direntry **); +static void cp_xdnm(u_char *, struct winentry *); +static void cp_sfn(u_char *, struct direntry *); +static off_t fsize(DOS_FS *, struct direntry *); +static int fatcnt(DOS_FS *, u_int); +static int fatget(DOS_FS *, u_int *); +static int fatend(u_int, u_int); +static int ioread(DOS_FS *, u_int, void *, u_int); +static int iobuf(DOS_FS *, u_int); +static int ioget(struct open_file *, u_int, void *, u_int); + +#define strcasecmp(s1, s2) dos_strcasecmp(s1, s2) +static int +strcasecmp(const char *s1, const char *s2) +{ + char c1, c2; + #define TO_UPPER(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c)) + for (;;) { + c1 = *s1++; + c2 = *s2++; + if (TO_UPPER(c1) != TO_UPPER(c2)) + return 1; + if (c1 == 0) + return 0; + } + #undef TO_UPPER +} + +/* + * Mount DOS filesystem + */ +static int +dos_mount(DOS_FS *fs, struct open_file *fd) +{ + int err; + + (void)memset(fs, 0, sizeof(DOS_FS)); + fs->fd = fd; + if ((err = !(fs->buf = alloc(SECSIZ)) ? errno : 0) || + (err = ioget(fs->fd, 0, fs->buf, 1)) || + (err = parsebs(fs, (DOS_BS *)fs->buf))) { + (void) dosunmount(fs); + return err; + } + return 0; +} + +#ifndef LIBSA_NO_FS_CLOSE +/* + * Unmount mounted filesystem + */ +static int +dos_unmount(DOS_FS *fs) +{ + int err; + + if (fs->links) + return EBUSY; + if ((err = dosunmount(fs))) + return err; + return 0; +} +#endif + +/* + * Common code shared by dos_mount() and dos_unmount() + */ +static int +dosunmount(DOS_FS *fs) +{ + if (fs->buf) + dealloc(fs->buf, SECSIZ); + dealloc(fs, sizeof(DOS_FS)); + return 0; +} + +/* + * Open DOS file + */ +__compactcall int +dosfs_open(const char *path, struct open_file *fd) +{ + const struct direntry *de; + DOS_FILE *f; + DOS_FS *fs; + u_int size, clus; + int err = 0; + + /* Allocate mount structure, associate with open */ + fs = alloc(sizeof(DOS_FS)); + + if ((err = dos_mount(fs, fd))) + goto out; + + if ((err = namede(fs, path, &de))) + goto out; + + clus = stclus(fs->fatsz, de); + size = getulong(de->deFileSize); + + if ((!(de->deAttributes & ATTR_DIRECTORY) && (!clus != !size)) || + ((de->deAttributes & ATTR_DIRECTORY) && size) || + (clus && !okclus(fs, clus))) { + err = EINVAL; + goto out; + } + + f = alloc(sizeof(DOS_FILE)); +#ifdef BOOTXX + /* due to __internal_memset_ causing all sorts of register spillage + (and being completely unoptimized for zeroing small amounts of + memory), if we hand-initialize the remaining members of f to zero, + the code size drops 68 bytes. This makes no sense, admittedly. */ + f->offset = 0; + f->c = 0; +#else + (void)memset(f, 0, sizeof(DOS_FILE)); +#endif + f->fs = fs; + fs->links++; + f->de = *de; + fd->f_fsdata = (void *)f; + fsmod = "msdos"; + +out: + return err; +} + +/* + * Read from file + */ +__compactcall int +dosfs_read(struct open_file *fd, void *vbuf, size_t nbyte, size_t *resid) +{ + off_t size; + u_int8_t *buf = vbuf; + u_int nb, off, clus, c, cnt, n; + DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; + int err = 0; + + nb = (u_int) nbyte; + if ((size = fsize(f->fs, &f->de)) == -1) + return EINVAL; + if (nb > (n = size - f->offset)) + nb = n; + off = f->offset; + if ((clus = stclus(f->fs->fatsz, &f->de))) + off &= f->fs->bsize - 1; + c = f->c; + cnt = nb; + while (cnt) { + n = 0; + if (!c) { + if ((c = clus)) + n = bytblk(f->fs, f->offset); + } else if (!off) { + n++; + } + while (n--) { + if ((err = fatget(f->fs, &c))) + goto out; + if (!okclus(f->fs, c)) { + err = EINVAL; + goto out; + } + } + if (!clus || (n = f->fs->bsize - off) > cnt) + n = cnt; + if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) : + secbyt(f->fs->lsndir)) + off, + buf, n))) + goto out; + f->offset += n; + f->c = c; + off = 0; + buf += n; + cnt -= n; + } +out: + if (resid) + *resid = nbyte - nb + cnt; + return err; +} + +#ifndef LIBSA_NO_FS_WRITE +/* + * Not implemented. + */ +__compactcall int +dosfs_write(struct open_file *fd, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !LIBSA_NO_FS_WRITE */ + +#ifndef LIBSA_NO_FS_SEEK +/* + * Reposition within file + */ +__compactcall off_t +dosfs_seek(struct open_file *fd, off_t offset, int whence) +{ + off_t off; + u_int size; + DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; + + size = getulong(f->de.deFileSize); + switch (whence) { + case SEEK_SET: + off = 0; + break; + case SEEK_CUR: + off = f->offset; + break; + case SEEK_END: + off = size; + break; + default: + return -1; + } + off += offset; + if (off < 0 || off > size) + return -1; + f->offset = (u_int) off; + f->c = 0; + return off; +} +#endif /* !LIBSA_NO_FS_SEEK */ + +#ifndef LIBSA_NO_FS_CLOSE +/* + * Close open file + */ +__compactcall int +dosfs_close(struct open_file *fd) +{ + DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; + DOS_FS *fs = f->fs; + + f->fs->links--; + dealloc(f, sizeof(DOS_FILE)); + dos_unmount(fs); + return 0; +} +#endif /* !LIBSA_NO_FS_CLOSE */ + +/* + * Return some stat information on a file. + */ +__compactcall int +dosfs_stat(struct open_file *fd, struct stat *sb) +{ + DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; + + /* only important stuff */ + sb->st_mode = (f->de.deAttributes & ATTR_DIRECTORY) ? + (S_IFDIR | 0555) : (S_IFREG | 0444); + sb->st_nlink = 1; + sb->st_uid = 0; + sb->st_gid = 0; + if ((sb->st_size = fsize(f->fs, &f->de)) == -1) + return EINVAL; + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +dosfs_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by dosfs\n"); + return; +} +#endif + +/* + * Parse DOS boot sector + */ +static int +parsebs(DOS_FS *fs, DOS_BS *bs) +{ + u_int sc; + + if ((bs->jmp[0] != 0x69 && + bs->jmp[0] != 0xe9 && + (bs->jmp[0] != 0xeb || bs->jmp[2] != 0x90)) || + bs->bpb.bpbMedia < 0xf0) + return EINVAL; + if (getushort(bs->bpb.bpbBytesPerSec) != SECSIZ) + return EINVAL; + if (!(fs->spc = bs->bpb.bpbSecPerClust) || fs->spc & (fs->spc - 1)) + return EINVAL; + fs->bsize = secbyt(fs->spc); + fs->bshift = ffs(fs->bsize) - 1; + if ((fs->spf = getushort(bs->bpb.bpbFATsecs))) { + if (bs->bpb.bpbFATs != 2) + return EINVAL; + if (!(fs->dirents = getushort(bs->bpb.bpbRootDirEnts))) + return EINVAL; + } else { + if (!(fs->spf = getulong(bs->bpb.bpbBigFATsecs))) + return EINVAL; + if (!bs->bpb.bpbFATs || bs->bpb.bpbFATs > 16) + return EINVAL; + if ((fs->rdcl = getulong(bs->bpb.bpbRootClust)) < LOCLUS) + return EINVAL; + } + if (!(fs->lsnfat = getushort(bs->bpb.bpbResSectors))) + return EINVAL; + fs->lsndir = fs->lsnfat + fs->spf * bs->bpb.bpbFATs; + fs->lsndta = fs->lsndir + entsec(fs->dirents); + if (!(sc = getushort(bs->bpb.bpbSectors)) && + !(sc = getulong(bs->bpb.bpbHugeSectors))) + return EINVAL; + if (fs->lsndta > sc) + return EINVAL; + if ((fs->xclus = secblk(fs, sc - fs->lsndta) + 1) < LOCLUS) + return EINVAL; + fs->fatsz = fs->dirents ? fs->xclus < 0xff6 ? 12 : 16 : 32; + sc = (secbyt(fs->spf) << 1) / (fs->fatsz >> 2) - 1; + if (fs->xclus > sc) + fs->xclus = sc; + return 0; +} + +/* + * Return directory entry from path + */ +static int +namede(DOS_FS *fs, const char *path, const struct direntry **dep) +{ + char name[256]; + const struct direntry *de; + char *s; + size_t n; + int err; + + err = 0; + de = dot; + if (*path == '/') + path++; + while (*path) { + if (!(s = strchr(path, '/'))) + s = strchr(path, 0); + if ((n = s - path) > 255) + return ENAMETOOLONG; + memcpy(name, path, n); + name[n] = 0; + path = s; + if (!(de->deAttributes & ATTR_DIRECTORY)) + return ENOTDIR; + if ((err = lookup(fs, stclus(fs->fatsz, de), name, &de))) + return err; + if (*path == '/') + path++; + } + *dep = de; + return 0; +} + +/* + * Lookup path segment + */ +static int +lookup(DOS_FS *fs, u_int clus, const char *name, const struct direntry **dep) +{ + static DOS_DIR *dir = NULL; + u_char lfn[261]; + u_char sfn[13]; + u_int nsec, lsec, xdn, chk, sec, ent, x; + int err = 0, ok, i; + + if (!clus) + for (ent = 0; ent < 2; ent++) + if (!strcasecmp(name, dotstr[ent])) { + *dep = dot + ent; + return 0; + } + + if (dir == NULL) { + dir = alloc(sizeof(DOS_DIR) * DEPSEC); + if (dir == NULL) + return ENOMEM; + } + + if (!clus && fs->fatsz == 32) + clus = fs->rdcl; + nsec = !clus ? entsec(fs->dirents) : fs->spc; + lsec = 0; + xdn = chk = 0; + for (;;) { + if (!clus && !lsec) + lsec = fs->lsndir; + else if (okclus(fs, clus)) + lsec = blklsn(fs, clus); + else { + err = EINVAL; + goto out; + } + for (sec = 0; sec < nsec; sec++) { + if ((err = ioget(fs->fd, lsec + sec, dir, 1))) + goto out; + for (ent = 0; ent < DEPSEC; ent++) { + if (!*dir[ent].de.deName) { + err = ENOENT; + goto out; + } + if (*dir[ent].de.deName != 0xe5) { + if (dir[ent].de.deAttributes == + ATTR_WIN95) { + x = dir[ent].xde.weCnt; + if (x & WIN_LAST || + (x + 1 == xdn && + dir[ent].xde.weChksum == + chk)) { + if (x & WIN_LAST) { + chk = dir[ent].xde.weChksum; + x &= WIN_CNT; + } + if (x >= 1 && x <= 20) { + cp_xdnm(lfn, &dir[ent].xde); + xdn = x; + continue; + } + } + } else if (!(dir[ent].de.deAttributes & + ATTR_VOLUME)) { + if ((ok = xdn == 1)) { + for (x = 0, i = 0; + i < 11; i++) + x = ((((x & 1) << 7) | (x >> 1)) + + dir[ent].de.deName[i]) & 0xff; + ok = chk == x && + !strcasecmp(name, (const char *)lfn); + } + if (!ok) { + cp_sfn(sfn, &dir[ent].de); + ok = !strcasecmp(name, (const char *)sfn); + } + if (ok) { + *dep = &dir[ent].de; + goto out2; + } + } + } + xdn = 0; + } + } + if (!clus) + break; + if ((err = fatget(fs, &clus))) + goto out; + if (fatend(fs->fatsz, clus)) + break; + } + err = ENOENT; + out: + dealloc(dir, sizeof(DOS_DIR) * DEPSEC); + dir = NULL; + out2: + return err; +} + +/* + * Copy name from extended directory entry + */ +static void +cp_xdnm(u_char *lfn, struct winentry *xde) +{ + static const struct { + u_int off; + u_int dim; + } ix[3] = { + { offsetof(struct winentry, wePart1), + sizeof(xde->wePart1) / 2 }, + { offsetof(struct winentry, wePart2), + sizeof(xde->wePart2) / 2 }, + { offsetof(struct winentry, wePart3), + sizeof(xde->wePart3) / 2 } + }; + u_char *p; + u_int n, x, c; + + lfn += 13 * ((xde->weCnt & WIN_CNT) - 1); + for (n = 0; n < 3; n++) + for (p = (u_char *)xde + ix[n].off, x = ix[n].dim; x; + p += 2, x--) { + if ((c = getushort(p)) && (c < 32 || c > 127)) + c = '?'; + if (!(*lfn++ = c)) + return; + } + if (xde->weCnt & WIN_LAST) + *lfn = 0; +} + +/* + * Copy short filename + */ +static void +cp_sfn(u_char *sfn, struct direntry *de) +{ + u_char *p; + int j, i; + + p = sfn; + if (*de->deName != ' ') { + for (j = 7; de->deName[j] == ' '; j--); + for (i = 0; i <= j; i++) + *p++ = de->deName[i]; + if (*de->deExtension != ' ') { + *p++ = '.'; + for (j = 2; de->deExtension[j] == ' '; j--); + for (i = 0; i <= j; i++) + *p++ = de->deExtension[i]; + } + } + *p = 0; + if (*sfn == 5) + *sfn = 0xe5; +} + +/* + * Return size of file in bytes + */ +static off_t +fsize(DOS_FS *fs, struct direntry *de) +{ + u_long size; + u_int c; + int n; + + if (!(size = getulong(de->deFileSize)) && + de->deAttributes & ATTR_DIRECTORY) { + if (!(c = getushort(de->deStartCluster))) { + size = fs->dirents * sizeof(struct direntry); + } else { + if ((n = fatcnt(fs, c)) == -1) + return n; + size = blkbyt(fs, n); + } + } + return size; +} + +/* + * Count number of clusters in chain + */ +static int +fatcnt(DOS_FS *fs, u_int c) +{ + int n; + + for (n = 0; okclus(fs, c); n++) + if (fatget(fs, &c)) + return -1; + return fatend(fs->fatsz, c) ? n : -1; +} + +/* + * Get next cluster in cluster chain + */ +static int +fatget(DOS_FS *fs, u_int *c) +{ + u_char buf[4]; + u_int x; + int err; + + err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf, + fs->fatsz != 32 ? 2 : 4); + if (err) + return err; + x = fs->fatsz != 32 ? getushort(buf) : getulong(buf); + *c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x; + return 0; +} + +/* + * Is cluster an end-of-chain marker? + */ +static int +fatend(u_int sz, u_int c) +{ + return c > (sz == 12 ? 0xff7U : sz == 16 ? 0xfff7U : 0xffffff7); +} + +/* + * Offset-based I/O primitive + */ +static int +ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte) +{ + char *s; + u_int off, n; + int err; + + s = buf; + if ((off = offset & (SECSIZ - 1))) { + offset -= off; + if ((err = iobuf(fs, bytsec(offset)))) + return err; + offset += SECSIZ; + if ((n = SECSIZ - off) > nbyte) + n = nbyte; + memcpy(s, fs->buf + off, n); + s += n; + nbyte -= n; + } + n = nbyte & (SECSIZ - 1); + if (nbyte -= n) { + if ((err = ioget(fs->fd, bytsec(offset), s, bytsec(nbyte)))) + return err; + offset += nbyte; + s += nbyte; + } + if (n) { + if ((err = iobuf(fs, bytsec(offset)))) + return err; + memcpy(s, fs->buf, n); + } + return 0; +} + +/* + * Buffered sector-based I/O primitive + */ +static int +iobuf(DOS_FS *fs, u_int lsec) +{ + int err; + + if (fs->bufsec != lsec) { + if ((err = ioget(fs->fd, lsec, fs->buf, 1))) + return err; + fs->bufsec = lsec; + } + return 0; +} + +/* + * Sector-based I/O primitive + */ +static int +ioget(struct open_file *fd, u_int lsec, void *buf, u_int nsec) +{ + size_t rsize; + int err; + +#ifndef LIBSA_NO_TWIDDLE + twiddle(); +#endif + err = DEV_STRATEGY(fd->f_dev)(fd->f_devdata, F_READ, lsec, + secbyt(nsec), buf, &rsize); + return err; +} diff --git a/sys/lib/libsa/dosfs.h b/sys/lib/libsa/dosfs.h new file mode 100644 index 000000000..3c1ca9e09 --- /dev/null +++ b/sys/lib/libsa/dosfs.h @@ -0,0 +1,30 @@ +/* $NetBSD: dosfs.h,v 1.3 2005/12/11 12:24:46 christos Exp $ */ + +/* + * Copyright (c) 1996, 1998 Robert Nordier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +FS_DEF(dosfs); diff --git a/sys/lib/libsa/errno.c b/sys/lib/libsa/errno.c new file mode 100644 index 000000000..b1eae171c --- /dev/null +++ b/sys/lib/libsa/errno.c @@ -0,0 +1,36 @@ +/* $NetBSD: errno.c,v 1.3 2005/12/11 12:24:46 christos Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)dev.c 8.1 (Berkeley) 6/11/93 + */ + +#include "stand.h" + +int errno; diff --git a/sys/lib/libsa/ether.c b/sys/lib/libsa/ether.c new file mode 100644 index 000000000..c70c381dd --- /dev/null +++ b/sys/lib/libsa/ether.c @@ -0,0 +1,124 @@ +/* $NetBSD: ether.c,v 1.22 2009/01/12 11:32:45 tsutsui Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include +#include + +#include "stand.h" +#include "net.h" + +/* Caller must leave room for ethernet header in front!! */ +ssize_t +sendether(struct iodesc *d, void *pkt, size_t len, u_char *dea, int etype) +{ + ssize_t n; + struct ether_header *eh; + +#ifdef ETHER_DEBUG + if (debug) + printf("sendether: called\n"); +#endif + + eh = (struct ether_header *)pkt - 1; + len += sizeof(*eh); + + MACPY(d->myea, eh->ether_shost); /* by byte */ + MACPY(dea, eh->ether_dhost); /* by byte */ + eh->ether_type = htons(etype); + + n = netif_put(d, eh, len); + if (n == -1 || (size_t)n < sizeof(*eh)) + return -1; + + n -= sizeof(*eh); + return n; +} + +/* + * Get a packet of any Ethernet type, with our address or + * the broadcast address. Save the Ether type in arg 5. + * NOTE: Caller must leave room for the Ether header. + */ +ssize_t +readether(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft, + u_int16_t *etype) +{ + ssize_t n; + struct ether_header *eh; + +#ifdef ETHER_DEBUG + if (debug) + printf("readether: called\n"); +#endif + + eh = (struct ether_header *)pkt - 1; + len += sizeof(*eh); + + n = netif_get(d, eh, len, tleft); + if (n == -1 || (size_t)n < sizeof(*eh)) + return -1; + + /* Validate Ethernet address. */ + if (memcmp(d->myea, eh->ether_dhost, 6) != 0 && + memcmp(bcea, eh->ether_dhost, 6) != 0) { +#ifdef ETHER_DEBUG + if (debug) + printf("readether: not ours (ea=%s)\n", + ether_sprintf(eh->ether_dhost)); +#endif + return -1; + } + *etype = ntohs(eh->ether_type); + + n -= sizeof(*eh); + return n; +} diff --git a/sys/lib/libsa/ether_sprintf.c b/sys/lib/libsa/ether_sprintf.c new file mode 100644 index 000000000..ae1fe92a3 --- /dev/null +++ b/sys/lib/libsa/ether_sprintf.c @@ -0,0 +1,73 @@ +/* $NetBSD: ether_sprintf.c,v 1.6 2007/11/24 13:20:55 isaki Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include "stand.h" +#include "net.h" + +/* + * Convert Ethernet address to printable (loggable) representation. + */ +char * +ether_sprintf(const u_char *ap) +{ + int i; + static char etherbuf[18]; + char *cp = etherbuf; + + for (i = 0; i < 6; i++) { + *cp++ = hexdigits[*ap >> 4]; + *cp++ = hexdigits[*ap++ & 0xf]; + *cp++ = ':'; + } + *--cp = 0; + return etherbuf; +} diff --git a/sys/lib/libsa/exec.c b/sys/lib/libsa/exec.c new file mode 100644 index 000000000..325a68fc7 --- /dev/null +++ b/sys/lib/libsa/exec.c @@ -0,0 +1,165 @@ +/* $NetBSD: exec.c,v 1.28 2009/12/29 20:21:46 elad Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#ifndef SA_EXEC_ANYOWNER +#include +#endif +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" + +void +exec(char *path, char *loadaddr, int howto) +{ +#ifndef SA_EXEC_ANYOWNER + struct stat sb; +#endif + struct exec x; + int io, i; + char *addr, *ssym, *esym; + + io = open(path, 0); + if (io < 0) + return; + +#ifndef SA_EXEC_ANYOWNER + (void) fstat(io, &sb); + if (sb.st_uid || (sb.st_mode & 2)) { + printf("non-secure file, will not load\n"); + close(io); + errno = EPERM; + return; + } +#endif + + i = read(io, (char *)&x, sizeof(x)); + if (i != sizeof(x) || N_BADMAG(x)) { + errno = EFTYPE; + return; + } + + /* Text */ + printf("%ld", x.a_text); + addr = loadaddr; + if (N_GETMAGIC(x) == ZMAGIC) { + (void)memcpy(addr, &x, sizeof(x)); + addr += sizeof(x); + x.a_text -= sizeof(x); + } + if (read(io, (char *)addr, x.a_text) != (ssize_t)x.a_text) + goto shread; + addr += x.a_text; + if (N_GETMAGIC(x) == ZMAGIC || N_GETMAGIC(x) == NMAGIC) + while ((long)addr & (N_PAGSIZ(x) - 1)) + *addr++ = 0; + + /* Data */ + printf("+%ld", x.a_data); + if (read(io, addr, x.a_data) != (ssize_t)x.a_data) + goto shread; + addr += x.a_data; + + /* Bss */ + printf("+%ld", x.a_bss); + for (i = 0; i < (int)x.a_bss; i++) + *addr++ = 0; + + /* Symbols */ + ssym = addr; + (void)memcpy(addr, &x.a_syms, sizeof(x.a_syms)); + addr += sizeof(x.a_syms); + if (x.a_syms) { + printf("+[%ld", x.a_syms); + if (read(io, addr, x.a_syms) != (ssize_t)x.a_syms) + goto shread; + addr += x.a_syms; + } + + i = 0; + if (x.a_syms && read(io, &i, sizeof(int)) != sizeof(int)) + goto shread; + + (void)memcpy(addr, &i, sizeof(int)); + if (i) { + i -= sizeof(int); + addr += sizeof(int); + if (read(io, addr, i) != i) + goto shread; + addr += i; + } + + if (x.a_syms) { + /* and that many bytes of (debug symbols?) */ + printf("+%d]", i); + } + + close(io); + +#define round_to_size(x) \ + (((int)(x) + sizeof(int) - 1) & ~(sizeof(int) - 1)) + esym = (char *)round_to_size(addr - loadaddr); +#undef round_to_size + + /* and note the end address of all this */ + printf(" total=0x%lx\n", (u_long)addr); + + /* + * Machine-dependent code must now adjust the + * entry point. This used to be done here, + * but some systems may need to relocate the + * loaded file before jumping to it, and the + * displayed start address would be wrong. + */ + +#ifdef EXEC_DEBUG + printf("ssym=0x%x esym=0x%x\n", ssym, esym); + printf("\n\nReturn to boot...\n"); + getchar(); +#endif + + machdep_start((char *)x.a_entry, howto, loadaddr, ssym, esym); + + /* exec failed */ + errno = ENOEXEC; + return; + +shread: + close(io); + errno = EIO; + return; +} diff --git a/sys/lib/libsa/exit.c b/sys/lib/libsa/exit.c new file mode 100644 index 000000000..cc7f1e24c --- /dev/null +++ b/sys/lib/libsa/exit.c @@ -0,0 +1,38 @@ +/* $NetBSD: exit.c,v 1.17 2007/11/24 13:20:55 isaki Exp $ */ + +/*- + * Copyright (c) 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stand.h" + +void +exit(int arg) +{ + panic("exit"); + /*NOTREACHED*/ +} diff --git a/sys/lib/libsa/ext2fs.c b/sys/lib/libsa/ext2fs.c new file mode 100644 index 000000000..dc3b49f96 --- /dev/null +++ b/sys/lib/libsa/ext2fs.c @@ -0,0 +1,1072 @@ +/* $NetBSD: ext2fs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* + * Copyright (c) 1997 Manuel Bouyer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Copyright (c) 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: David Golub + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Stand-alone file reading package for Ext2 file system. + */ + +/* #define EXT2FS_DEBUG */ + +#include +#include +#include +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "ext2fs.h" + +#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK) +#define LIBSA_NO_FS_SYMLINK +#endif + +#if defined(LIBSA_NO_TWIDDLE) +#define twiddle() +#endif + +#ifndef indp_t +#define indp_t int32_t +#endif +typedef uint32_t ino32_t; +#ifndef FSBTODB +#define FSBTODB(fs, indp) fsbtodb(fs, indp) +#endif + +/* + * To avoid having a lot of filesystem-block sized buffers lurking (which + * could be 32k) we only keep a few entries of the indirect block map. + * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block + * ~13 times pulling in a 6M kernel. + * The cache size must be smaller than the smallest filesystem block, + * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks). + */ +#define LN2_IND_CACHE_SZ 6 +#define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ) +#define IND_CACHE_MASK (IND_CACHE_SZ - 1) + +/* + * In-core open file. + */ +struct file { + off_t f_seekp; /* seek pointer */ + struct m_ext2fs *f_fs; /* pointer to super-block */ + struct ext2fs_dinode f_di; /* copy of on-disk inode */ + uint f_nishift; /* for blocks in indirect block */ + indp_t f_ind_cache_block; + indp_t f_ind_cache[IND_CACHE_SZ]; + + char *f_buf; /* buffer for data block */ + size_t f_buf_size; /* size of data block */ + daddr_t f_buf_blkno; /* block number of data block */ +}; + +#if defined(LIBSA_ENABLE_LS_OP) + +#define NELEM(x) (sizeof (x) / sizeof(*x)) + +typedef struct entry_t entry_t; +struct entry_t { + entry_t *e_next; + ino32_t e_ino; + uint8_t e_type; + char e_name[1]; +}; + +static const char *const typestr[] = { + "unknown", + "REG", + "DIR", + "CHR", + "BLK", + "FIFO", + "SOCK", + "LNK" +}; + +static int +fn_match(const char *fname, const char *pattern) +{ + char fc, pc; + + do { + fc = *fname++; + pc = *pattern++; + if (!fc && !pc) + return 1; + if (pc == '?' && fc) + pc = fc; + } while (fc == pc); + + if (pc != '*') + return 0; + /* + * Too hard (and unnecessary really) too check for "*?name" etc.... + * "**" will look for a '*' and "*?" a '?' + */ + pc = *pattern++; + if (!pc) + return 1; + while ((fname = strchr(fname, pc))) + if (fn_match(++fname, pattern)) + return 1; + return 0; +} +#endif /* LIBSA_ENABLE_LS_OP */ + +static int read_inode(ino32_t, struct open_file *); +static int block_map(struct open_file *, indp_t, indp_t *); +static int buf_read_file(struct open_file *, char **, size_t *); +static int search_directory(const char *, int, struct open_file *, ino32_t *); +static int read_sblock(struct open_file *, struct m_ext2fs *); +static int read_gdblock(struct open_file *, struct m_ext2fs *); +#ifdef EXT2FS_DEBUG +static void dump_sblock(struct m_ext2fs *); +#endif + +/* + * Read a new inode into a file structure. + */ +static int +read_inode(ino32_t inumber, struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct m_ext2fs *fs = fp->f_fs; + char *buf; + size_t rsize; + int rc; + daddr_t inode_sector; + struct ext2fs_dinode *dip; + + inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); + + /* + * Read inode and save it. + */ + buf = fp->f_buf; + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + inode_sector, fs->e2fs_bsize, buf, &rsize); + if (rc) + return rc; + if (rsize != fs->e2fs_bsize) + return EIO; + + dip = (struct ext2fs_dinode *)(buf + + EXT2_DINODE_SIZE(fs) * ino_to_fsbo(fs, inumber)); + e2fs_iload(dip, &fp->f_di); + + /* + * Clear out the old buffers + */ + fp->f_ind_cache_block = ~0; + fp->f_buf_blkno = -1; + return rc; +} + +/* + * Given an offset in a file, find the disk block number that + * contains that block. + */ +static int +block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct m_ext2fs *fs = fp->f_fs; + uint level; + indp_t ind_cache; + indp_t ind_block_num; + size_t rsize; + int rc; + indp_t *buf = (void *)fp->f_buf; + + /* + * Index structure of an inode: + * + * e2di_blocks[0..NDADDR-1] + * hold block numbers for blocks + * 0..NDADDR-1 + * + * e2di_blocks[NDADDR+0] + * block NDADDR+0 is the single indirect block + * holds block numbers for blocks + * NDADDR .. NDADDR + NINDIR(fs)-1 + * + * e2di_blocks[NDADDR+1] + * block NDADDR+1 is the double indirect block + * holds block numbers for INDEX blocks for blocks + * NDADDR + NINDIR(fs) .. + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 + * + * e2di_blocks[NDADDR+2] + * block NDADDR+2 is the triple indirect block + * holds block numbers for double-indirect + * blocks for blocks + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 + * + NINDIR(fs)**3 - 1 + */ + + if (file_block < NDADDR) { + /* Direct block. */ + *disk_block_p = fs2h32(fp->f_di.e2di_blocks[file_block]); + return 0; + } + + file_block -= NDADDR; + + ind_cache = file_block >> LN2_IND_CACHE_SZ; + if (ind_cache == fp->f_ind_cache_block) { + *disk_block_p = + fs2h32(fp->f_ind_cache[file_block & IND_CACHE_MASK]); + return 0; + } + + for (level = 0;;) { + level += fp->f_nishift; + if (file_block < (indp_t)1 << level) + break; + if (level > NIADDR * fp->f_nishift) + /* Block number too high */ + return EFBIG; + file_block -= (indp_t)1 << level; + } + + ind_block_num = + fs2h32(fp->f_di.e2di_blocks[NDADDR + (level / fp->f_nishift - 1)]); + + for (;;) { + level -= fp->f_nishift; + if (ind_block_num == 0) { + *disk_block_p = 0; /* missing */ + return 0; + } + + twiddle(); + /* + * If we were feeling brave, we could work out the number + * of the disk sector and read a single disk sector instead + * of a filesystem block. + * However we don't do this very often anyway... + */ + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fp->f_fs, ind_block_num), fs->e2fs_bsize, + buf, &rsize); + if (rc) + return rc; + if (rsize != fs->e2fs_bsize) + return EIO; + ind_block_num = fs2h32(buf[file_block >> level]); + if (level == 0) + break; + file_block &= (1 << level) - 1; + } + + /* Save the part of the block that contains this sector */ + memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK], + IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); + fp->f_ind_cache_block = ind_cache; + + *disk_block_p = ind_block_num; + + return 0; +} + +/* + * Read a portion of a file into an internal buffer. + * Return the location in the buffer and the amount in the buffer. + */ +static int +buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct m_ext2fs *fs = fp->f_fs; + long off; + indp_t file_block; + indp_t disk_block; + size_t block_size; + int rc; + + off = blkoff(fs, fp->f_seekp); + file_block = lblkno(fs, fp->f_seekp); + block_size = fs->e2fs_bsize; /* no fragment */ + + if (file_block != fp->f_buf_blkno) { + rc = block_map(f, file_block, &disk_block); + if (rc) + return rc; + + if (disk_block == 0) { + memset(fp->f_buf, 0, block_size); + fp->f_buf_size = block_size; + } else { + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fs, disk_block), + block_size, fp->f_buf, &fp->f_buf_size); + if (rc) + return rc; + } + + fp->f_buf_blkno = file_block; + } + + /* + * Return address of byte in buffer corresponding to + * offset, and size of remainder of buffer after that + * byte. + */ + *buf_p = fp->f_buf + off; + *size_p = block_size - off; + + /* + * But truncate buffer at end of file. + */ + /* XXX should handle LARGEFILE */ + if (*size_p > fp->f_di.e2di_size - fp->f_seekp) + *size_p = fp->f_di.e2di_size - fp->f_seekp; + + return 0; +} + +/* + * Search a directory for a name and return its + * inode number. + */ +static int +search_directory(const char *name, int length, struct open_file *f, + ino32_t *inumber_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct ext2fs_direct *dp; + struct ext2fs_direct *edp; + char *buf; + size_t buf_size; + int namlen; + int rc; + + fp->f_seekp = 0; + /* XXX should handle LARGEFILE */ + while (fp->f_seekp < (off_t)fp->f_di.e2di_size) { + rc = buf_read_file(f, &buf, &buf_size); + if (rc) + return rc; + + dp = (struct ext2fs_direct *)buf; + edp = (struct ext2fs_direct *)(buf + buf_size); + for (; dp < edp; + dp = (void *)((char *)dp + fs2h16(dp->e2d_reclen))) { + if (fs2h16(dp->e2d_reclen) <= 0) + break; + if (fs2h32(dp->e2d_ino) == (ino32_t)0) + continue; + namlen = dp->e2d_namlen; + if (namlen == length && + !memcmp(name, dp->e2d_name, length)) { + /* found entry */ + *inumber_p = fs2h32(dp->e2d_ino); + return 0; + } + } + fp->f_seekp += buf_size; + } + return ENOENT; +} + +int +read_sblock(struct open_file *f, struct m_ext2fs *fs) +{ + static uint8_t sbbuf[SBSIZE]; + struct ext2fs ext2fs; + size_t buf_size; + int rc; + + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + SBOFF / DEV_BSIZE, SBSIZE, sbbuf, &buf_size); + if (rc) + return rc; + + if (buf_size != SBSIZE) + return EIO; + + e2fs_sbload((void *)sbbuf, &ext2fs); + if (ext2fs.e2fs_magic != E2FS_MAGIC) + return EINVAL; + if (ext2fs.e2fs_rev > E2FS_REV1 || + (ext2fs.e2fs_rev == E2FS_REV1 && + (ext2fs.e2fs_first_ino != EXT2_FIRSTINO || + (ext2fs.e2fs_inode_size != 128 && ext2fs.e2fs_inode_size != 256) || + ext2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP))) { + return ENODEV; + } + + e2fs_sbload((void *)sbbuf, &fs->e2fs); + /* compute in-memory m_ext2fs values */ + fs->e2fs_ncg = + howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, + fs->e2fs.e2fs_bpg); + /* XXX assume hw bsize = 512 */ + fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; + fs->e2fs_bsize = MINBSIZE << fs->e2fs.e2fs_log_bsize; + fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; + fs->e2fs_qbmask = fs->e2fs_bsize - 1; + fs->e2fs_bmask = ~fs->e2fs_qbmask; + fs->e2fs_ngdb = + howmany(fs->e2fs_ncg, fs->e2fs_bsize / sizeof(struct ext2_gd)); + fs->e2fs_ipb = fs->e2fs_bsize / ext2fs.e2fs_inode_size; + fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb; + + return 0; +} + +int +read_gdblock(struct open_file *f, struct m_ext2fs *fs) +{ + struct file *fp = (struct file *)f->f_fsdata; + size_t rsize; + uint gdpb; + int i, rc; + + gdpb = fs->e2fs_bsize / sizeof(struct ext2_gd); + + for (i = 0; i < fs->e2fs_ngdb; i++) { + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fs, fs->e2fs.e2fs_first_dblock + + 1 /* superblock */ + i), + fs->e2fs_bsize, fp->f_buf, &rsize); + if (rc) + return rc; + if (rsize != fs->e2fs_bsize) + return EIO; + + e2fs_cgload((struct ext2_gd *)fp->f_buf, + &fs->e2fs_gd[i * gdpb], + (i == (fs->e2fs_ngdb - 1)) ? + (fs->e2fs_ncg - gdpb * i) * sizeof(struct ext2_gd): + fs->e2fs_bsize); + } + + return 0; +} + + +/* + * Open a file. + */ +__compactcall int +ext2fs_open(const char *path, struct open_file *f) +{ +#ifndef LIBSA_FS_SINGLECOMPONENT + const char *cp, *ncp; + int c; +#endif + ino32_t inumber; + struct file *fp; + struct m_ext2fs *fs; + int rc; +#ifndef LIBSA_NO_FS_SYMLINK + ino32_t parent_inumber; + int nlinks = 0; + char namebuf[MAXPATHLEN+1]; + char *buf; +#endif + + /* allocate file system specific data structure */ + fp = alloc(sizeof(struct file)); + memset(fp, 0, sizeof(struct file)); + f->f_fsdata = (void *)fp; + + /* allocate space and read super block */ + fs = alloc(sizeof(*fs)); + memset(fs, 0, sizeof(*fs)); + fp->f_fs = fs; + twiddle(); + + rc = read_sblock(f, fs); + if (rc) + goto out; + +#ifdef EXT2FS_DEBUG + dump_sblock(fs); +#endif + + /* alloc a block sized buffer used for all fs transfers */ + fp->f_buf = alloc(fs->e2fs_bsize); + + /* read group descriptor blocks */ + fs->e2fs_gd = alloc(sizeof(struct ext2_gd) * fs->e2fs_ncg); + rc = read_gdblock(f, fs); + if (rc) + goto out; + + /* + * Calculate indirect block levels. + */ + { + indp_t mult; + int ln2; + + /* + * We note that the number of indirect blocks is always + * a power of 2. This lets us use shifts and masks instead + * of divide and remainder and avoinds pulling in the + * 64bit division routine into the boot code. + */ + mult = NINDIR(fs); +#ifdef DEBUG + if (!powerof2(mult)) { + /* Hummm was't a power of 2 */ + rc = EINVAL; + goto out; + } +#endif + for (ln2 = 0; mult != 1; ln2++) + mult >>= 1; + + fp->f_nishift = ln2; + } + + inumber = EXT2_ROOTINO; + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_FS_SINGLECOMPONENT + cp = path; + while (*cp) { + + /* + * Remove extra separators + */ + while (*cp == '/') + cp++; + if (*cp == '\0') + break; + + /* + * Check that current node is a directory. + */ + if ((fp->f_di.e2di_mode & EXT2_IFMT) != EXT2_IFDIR) { + rc = ENOTDIR; + goto out; + } + + /* + * Get next component of path name. + */ + ncp = cp; + while ((c = *cp) != '\0' && c != '/') + cp++; + + /* + * Look up component in current directory. + * Save directory inumber in case we find a + * symbolic link. + */ +#ifndef LIBSA_NO_FS_SYMLINK + parent_inumber = inumber; +#endif + rc = search_directory(ncp, cp - ncp, f, &inumber); + if (rc) + goto out; + + /* + * Open next component. + */ + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_NO_FS_SYMLINK + /* + * Check for symbolic link. + */ + if ((fp->f_di.e2di_mode & EXT2_IFMT) == EXT2_IFLNK) { + /* XXX should handle LARGEFILE */ + int link_len = fp->f_di.e2di_size; + int len; + + len = strlen(cp); + + if (link_len + len > MAXPATHLEN || + ++nlinks > MAXSYMLINKS) { + rc = ENOENT; + goto out; + } + + memmove(&namebuf[link_len], cp, len + 1); + + if (link_len < EXT2_MAXSYMLINKLEN) { + memcpy(namebuf, fp->f_di.e2di_blocks, link_len); + } else { + /* + * Read file for symbolic link + */ + size_t buf_size; + indp_t disk_block; + + buf = fp->f_buf; + rc = block_map(f, (indp_t)0, &disk_block); + if (rc) + goto out; + + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, + F_READ, FSBTODB(fs, disk_block), + fs->e2fs_bsize, buf, &buf_size); + if (rc) + goto out; + + memcpy(namebuf, buf, link_len); + } + + /* + * If relative pathname, restart at parent directory. + * If absolute pathname, restart at root. + */ + cp = namebuf; + if (*cp != '/') + inumber = parent_inumber; + else + inumber = (ino32_t)EXT2_ROOTINO; + + if ((rc = read_inode(inumber, f)) != 0) + goto out; + } +#endif /* !LIBSA_NO_FS_SYMLINK */ + } + + /* + * Found terminal component. + */ + rc = 0; + +#else /* !LIBSA_FS_SINGLECOMPONENT */ + + /* look up component in the current (root) directory */ + rc = search_directory(path, strlen(path), f, &inumber); + if (rc) + goto out; + + /* open it */ + rc = read_inode(inumber, f); + +#endif /* !LIBSA_FS_SINGLECOMPONENT */ + + fp->f_seekp = 0; /* reset seek pointer */ + +out: + if (rc) + ext2fs_close(f); + else { + fsmod = "ext2fs"; + fsmod2 = "ffs"; + } + return rc; +} + +__compactcall int +ext2fs_close(struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + + f->f_fsdata = NULL; + if (fp == NULL) + return 0; + + if (fp->f_fs->e2fs_gd) + dealloc(fp->f_fs->e2fs_gd, + sizeof(struct ext2_gd) * fp->f_fs->e2fs_ncg); + if (fp->f_buf) + dealloc(fp->f_buf, fp->f_fs->e2fs_bsize); + dealloc(fp->f_fs, sizeof(*fp->f_fs)); + dealloc(fp, sizeof(struct file)); + return 0; +} + +/* + * Copy a portion of a file into kernel memory. + * Cross block boundaries when necessary. + */ +__compactcall int +ext2fs_read(struct open_file *f, void *start, size_t size, size_t *resid) +{ + struct file *fp = (struct file *)f->f_fsdata; + size_t csize; + char *buf; + size_t buf_size; + int rc = 0; + char *addr = start; + + while (size != 0) { + /* XXX should handle LARGEFILE */ + if (fp->f_seekp >= (off_t)fp->f_di.e2di_size) + break; + + rc = buf_read_file(f, &buf, &buf_size); + if (rc) + break; + + csize = size; + if (csize > buf_size) + csize = buf_size; + + memcpy(addr, buf, csize); + + fp->f_seekp += csize; + addr += csize; + size -= csize; + } + if (resid) + *resid = size; + return rc; +} + +/* + * Not implemented. + */ +#ifndef LIBSA_NO_FS_WRITE +__compactcall int +ext2fs_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !LIBSA_NO_FS_WRITE */ + +#ifndef LIBSA_NO_FS_SEEK +__compactcall off_t +ext2fs_seek(struct open_file *f, off_t offset, int where) +{ + struct file *fp = (struct file *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + fp->f_seekp = offset; + break; + case SEEK_CUR: + fp->f_seekp += offset; + break; + case SEEK_END: + /* XXX should handle LARGEFILE */ + fp->f_seekp = fp->f_di.e2di_size - offset; + break; + default: + return -1; + } + return fp->f_seekp; +} +#endif /* !LIBSA_NO_FS_SEEK */ + +__compactcall int +ext2fs_stat(struct open_file *f, struct stat *sb) +{ + struct file *fp = (struct file *)f->f_fsdata; + + /* only important stuff */ + memset(sb, 0, sizeof *sb); + sb->st_mode = fp->f_di.e2di_mode; + sb->st_uid = fp->f_di.e2di_uid; + sb->st_gid = fp->f_di.e2di_gid; + /* XXX should handle LARGEFILE */ + sb->st_size = fp->f_di.e2di_size; + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +ext2fs_ls(struct open_file *f, const char *pattern) +{ + struct file *fp = (struct file *)f->f_fsdata; + size_t block_size = fp->f_fs->e2fs_bsize; + char *buf; + size_t buf_size; + entry_t *names = 0, *n, **np; + + fp->f_seekp = 0; + while (fp->f_seekp < (off_t)fp->f_di.e2di_size) { + struct ext2fs_direct *dp, *edp; + int rc = buf_read_file(f, &buf, &buf_size); + if (rc) + goto out; + if (buf_size != block_size || buf_size == 0) + goto out; + + dp = (struct ext2fs_direct *)buf; + edp = (struct ext2fs_direct *)(buf + buf_size); + + for (; dp < edp; + dp = (void *)((char *)dp + fs2h16(dp->e2d_reclen))) { + const char *t; + + if (fs2h16(dp->e2d_reclen) <= 0) + goto out; + + if (fs2h32(dp->e2d_ino) == 0) + continue; + + if (dp->e2d_type >= NELEM(typestr) || + !(t = typestr[dp->e2d_type])) { + /* + * This does not handle "old" + * filesystems properly. On little + * endian machines, we get a bogus + * type name if the namlen matches a + * valid type identifier. We could + * check if we read namlen "0" and + * handle this case specially, if + * there were a pressing need... + */ + printf("bad dir entry\n"); + goto out; + } + if (pattern && !fn_match(dp->e2d_name, pattern)) + continue; + n = alloc(sizeof *n + strlen(dp->e2d_name)); + if (!n) { + printf("%d: %s (%s)\n", + fs2h32(dp->e2d_ino), dp->e2d_name, t); + continue; + } + n->e_ino = fs2h32(dp->e2d_ino); + n->e_type = dp->e2d_type; + strcpy(n->e_name, dp->e2d_name); + for (np = &names; *np; np = &(*np)->e_next) { + if (strcmp(n->e_name, (*np)->e_name) < 0) + break; + } + n->e_next = *np; + *np = n; + } + fp->f_seekp += buf_size; + } + + if (names) { + entry_t *p_names = names; + do { + n = p_names; + printf("%d: %s (%s)\n", + n->e_ino, n->e_name, typestr[n->e_type]); + p_names = n->e_next; + } while (p_names); + } else { + printf("not found\n"); + } +out: + if (names) { + do { + n = names; + names = n->e_next; + dealloc(n, 0); + } while (names); + } + return; +} +#endif + +/* + * byte swap functions for big endian machines + * (ext2fs is always little endian) + * + * XXX: We should use src/sys/ufs/ext2fs/ext2fs_bswap.c + */ + +/* These functions are only needed if native byte order is not big endian */ +#if BYTE_ORDER == BIG_ENDIAN +void +e2fs_sb_bswap(struct ext2fs *old, struct ext2fs *new) +{ + + /* preserve unused fields */ + memcpy(new, old, sizeof(struct ext2fs)); + new->e2fs_icount = bswap32(old->e2fs_icount); + new->e2fs_bcount = bswap32(old->e2fs_bcount); + new->e2fs_rbcount = bswap32(old->e2fs_rbcount); + new->e2fs_fbcount = bswap32(old->e2fs_fbcount); + new->e2fs_ficount = bswap32(old->e2fs_ficount); + new->e2fs_first_dblock = bswap32(old->e2fs_first_dblock); + new->e2fs_log_bsize = bswap32(old->e2fs_log_bsize); + new->e2fs_fsize = bswap32(old->e2fs_fsize); + new->e2fs_bpg = bswap32(old->e2fs_bpg); + new->e2fs_fpg = bswap32(old->e2fs_fpg); + new->e2fs_ipg = bswap32(old->e2fs_ipg); + new->e2fs_mtime = bswap32(old->e2fs_mtime); + new->e2fs_wtime = bswap32(old->e2fs_wtime); + new->e2fs_mnt_count = bswap16(old->e2fs_mnt_count); + new->e2fs_max_mnt_count = bswap16(old->e2fs_max_mnt_count); + new->e2fs_magic = bswap16(old->e2fs_magic); + new->e2fs_state = bswap16(old->e2fs_state); + new->e2fs_beh = bswap16(old->e2fs_beh); + new->e2fs_minrev = bswap16(old->e2fs_minrev); + new->e2fs_lastfsck = bswap32(old->e2fs_lastfsck); + new->e2fs_fsckintv = bswap32(old->e2fs_fsckintv); + new->e2fs_creator = bswap32(old->e2fs_creator); + new->e2fs_rev = bswap32(old->e2fs_rev); + new->e2fs_ruid = bswap16(old->e2fs_ruid); + new->e2fs_rgid = bswap16(old->e2fs_rgid); + new->e2fs_first_ino = bswap32(old->e2fs_first_ino); + new->e2fs_inode_size = bswap16(old->e2fs_inode_size); + new->e2fs_block_group_nr = bswap16(old->e2fs_block_group_nr); + new->e2fs_features_compat = bswap32(old->e2fs_features_compat); + new->e2fs_features_incompat = bswap32(old->e2fs_features_incompat); + new->e2fs_features_rocompat = bswap32(old->e2fs_features_rocompat); + new->e2fs_algo = bswap32(old->e2fs_algo); + new->e2fs_reserved_ngdb = bswap16(old->e2fs_reserved_ngdb); +} + +void e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size) +{ + int i; + + for (i = 0; i < (size / sizeof(struct ext2_gd)); i++) { + new[i].ext2bgd_b_bitmap = bswap32(old[i].ext2bgd_b_bitmap); + new[i].ext2bgd_i_bitmap = bswap32(old[i].ext2bgd_i_bitmap); + new[i].ext2bgd_i_tables = bswap32(old[i].ext2bgd_i_tables); + new[i].ext2bgd_nbfree = bswap16(old[i].ext2bgd_nbfree); + new[i].ext2bgd_nifree = bswap16(old[i].ext2bgd_nifree); + new[i].ext2bgd_ndirs = bswap16(old[i].ext2bgd_ndirs); + } +} + +void e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new) +{ + + new->e2di_mode = bswap16(old->e2di_mode); + new->e2di_uid = bswap16(old->e2di_uid); + new->e2di_gid = bswap16(old->e2di_gid); + new->e2di_nlink = bswap16(old->e2di_nlink); + new->e2di_size = bswap32(old->e2di_size); + new->e2di_atime = bswap32(old->e2di_atime); + new->e2di_ctime = bswap32(old->e2di_ctime); + new->e2di_mtime = bswap32(old->e2di_mtime); + new->e2di_dtime = bswap32(old->e2di_dtime); + new->e2di_nblock = bswap32(old->e2di_nblock); + new->e2di_flags = bswap32(old->e2di_flags); + new->e2di_gen = bswap32(old->e2di_gen); + new->e2di_facl = bswap32(old->e2di_facl); + new->e2di_dacl = bswap32(old->e2di_dacl); + new->e2di_faddr = bswap32(old->e2di_faddr); + memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0], + (NDADDR + NIADDR) * sizeof(uint32_t)); +} +#endif + +#ifdef EXT2FS_DEBUG +void +dump_sblock(struct m_ext2fs *fs) +{ + + printf("fs->e2fs.e2fs_bcount = %u\n", fs->e2fs.e2fs_bcount); + printf("fs->e2fs.e2fs_first_dblock = %u\n", fs->e2fs.e2fs_first_dblock); + printf("fs->e2fs.e2fs_log_bsize = %u\n", fs->e2fs.e2fs_log_bsize); + printf("fs->e2fs.e2fs_bpg = %u\n", fs->e2fs.e2fs_bpg); + printf("fs->e2fs.e2fs_ipg = %u\n", fs->e2fs.e2fs_ipg); + printf("fs->e2fs.e2fs_magic = 0x%x\n", fs->e2fs.e2fs_magic); + printf("fs->e2fs.e2fs_rev = %u\n", fs->e2fs.e2fs_rev); + + if (fs->e2fs.e2fs_rev == E2FS_REV1) { + printf("fs->e2fs.e2fs_first_ino = %u\n", + fs->e2fs.e2fs_first_ino); + printf("fs->e2fs.e2fs_inode_size = %u\n", + fs->e2fs.e2fs_inode_size); + printf("fs->e2fs.e2fs_features_compat = %u\n", + fs->e2fs.e2fs_features_compat); + printf("fs->e2fs.e2fs_features_incompat = %u\n", + fs->e2fs.e2fs_features_incompat); + printf("fs->e2fs.e2fs_features_rocompat = %u\n", + fs->e2fs.e2fs_features_rocompat); + printf("fs->e2fs.e2fs_reserved_ngdb = %u\n", + fs->e2fs.e2fs_reserved_ngdb); + } + + printf("fs->e2fs_bsize = %u\n", fs->e2fs_bsize); + printf("fs->e2fs_fsbtodb = %u\n", fs->e2fs_fsbtodb); + printf("fs->e2fs_ncg = %u\n", fs->e2fs_ncg); + printf("fs->e2fs_ngdb = %u\n", fs->e2fs_ngdb); + printf("fs->e2fs_ipb = %u\n", fs->e2fs_ipb); + printf("fs->e2fs_itpg = %u\n", fs->e2fs_itpg); +} +#endif diff --git a/sys/lib/libsa/ext2fs.h b/sys/lib/libsa/ext2fs.h new file mode 100644 index 000000000..a7add8e5b --- /dev/null +++ b/sys/lib/libsa/ext2fs.h @@ -0,0 +1,34 @@ +/* $NetBSD: ext2fs.h,v 1.1 2007/12/01 18:06:22 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs.h 8.1 (Berkeley) 6/11/93 + */ + +FS_DEF(ext2fs); diff --git a/sys/lib/libsa/ffsv1.c b/sys/lib/libsa/ffsv1.c new file mode 100644 index 000000000..6fb1caaf8 --- /dev/null +++ b/sys/lib/libsa/ffsv1.c @@ -0,0 +1,20 @@ +/* $NetBSD: ffsv1.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */ + +#define LIBSA_FFSv1 + +#define ufs_open ffsv1_open +#define ufs_close ffsv1_close +#define ufs_read ffsv1_read +#define ufs_write ffsv1_write +#define ufs_seek ffsv1_seek +#define ufs_stat ffsv1_stat +#if defined(LIBSA_ENABLE_LS_OP) +#define ufs_ls ffsv1_ls +#endif + +#define ufs_dinode ufs1_dinode +#define indp_t int32_t + +#define FSMOD "ffs" + +#include "ufs.c" diff --git a/sys/lib/libsa/ffsv2.c b/sys/lib/libsa/ffsv2.c new file mode 100644 index 000000000..a5e5585ea --- /dev/null +++ b/sys/lib/libsa/ffsv2.c @@ -0,0 +1,20 @@ +/* $NetBSD: ffsv2.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */ + +#define LIBSA_FFSv2 + +#define ufs_open ffsv2_open +#define ufs_close ffsv2_close +#define ufs_read ffsv2_read +#define ufs_write ffsv2_write +#define ufs_seek ffsv2_seek +#define ufs_stat ffsv2_stat +#if defined(LIBSA_ENABLE_LS_OP) +#define ufs_ls ffsv2_ls +#endif + +#define ufs_dinode ufs2_dinode +#define indp_t int64_t + +#define FSMOD "ffs" + +#include "ufs.c" diff --git a/sys/lib/libsa/files.c b/sys/lib/libsa/files.c new file mode 100644 index 000000000..ab216b1d9 --- /dev/null +++ b/sys/lib/libsa/files.c @@ -0,0 +1,12 @@ +/* $NetBSD: files.c,v 1.1 2002/03/15 13:23:34 simonb Exp $ */ + +/* + * files.c: + * + * libsa file table. separate from other global variables so that + * all of those don't need to be linked in just to use open, et al. + */ + +#include "stand.h" + +struct open_file files[SOPEN_MAX]; diff --git a/sys/lib/libsa/fstat.c b/sys/lib/libsa/fstat.c new file mode 100644 index 000000000..0b4fc8b73 --- /dev/null +++ b/sys/lib/libsa/fstat.c @@ -0,0 +1,58 @@ +/* $NetBSD: fstat.c,v 1.7 2007/12/02 04:59:25 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stat.c 8.1 (Berkeley) 6/11/93 + */ + +#include "stand.h" + +int +fstat(int fd, struct stat *sb) +{ + struct open_file *f = &files[fd]; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + return -1; + } +#endif + +#if !defined(LIBSA_NO_RAW_ACCESS) + /* operation not defined on raw devices */ + if (f->f_flags & F_RAW) { + errno = EOPNOTSUPP; + return -1; + } +#endif + + errno = FS_STAT(f->f_ops)(f, sb); /* XXX no point setting errno */ + return 0; +} diff --git a/sys/lib/libsa/getfile.c b/sys/lib/libsa/getfile.c new file mode 100644 index 000000000..ef2d1e037 --- /dev/null +++ b/sys/lib/libsa/getfile.c @@ -0,0 +1,51 @@ +/* $NetBSD: getfile.c,v 1.9 2007/11/24 13:20:55 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)getfile.c 8.1 (Berkeley) 6/11/93 + */ +#include "stand.h" + +#define CTRL(x) ((x) & 037) + +int +getfile(char *prompt, int mode) +{ + int fd; + char buf[100]; + + do { + printf("%s: ", prompt); + gets(buf); + if (buf[0] == CTRL('d') && buf[1] == 0) + return -1; + } while ((fd = open(buf, mode)) < 0); + + return fd; +} diff --git a/sys/lib/libsa/gets.c b/sys/lib/libsa/gets.c new file mode 100644 index 000000000..1cda43321 --- /dev/null +++ b/sys/lib/libsa/gets.c @@ -0,0 +1,87 @@ +/* $NetBSD: gets.c,v 1.10 2007/11/24 13:20:55 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)gets.c 8.1 (Berkeley) 6/11/93 + */ + +#include "stand.h" + +void +gets(char *buf) +{ + int c; + char *lp; + + for (lp = buf;;) { + switch (c = getchar() & 0177) { + case '\n': + case '\r': + *lp = '\0'; + putchar('\n'); + return; + case '\b': + case '\177': + if (lp > buf) { + lp--; + putchar('\b'); + putchar(' '); + putchar('\b'); + } + break; +#if HASH_ERASE + case '#': + if (lp > buf) + --lp; + break; +#endif + case 'r' & 037: { + char *p; + + putchar('\n'); + for (p = buf; p < lp; ++p) + putchar(*p); + break; + } +#if AT_ERASE + case '@': +#endif + case 'u' & 037: + case 'w' & 037: + lp = buf; + putchar('\n'); + break; + default: + *lp++ = c; + putchar(c); + break; + } + } + /*NOTREACHED*/ +} diff --git a/sys/lib/libsa/globals.c b/sys/lib/libsa/globals.c new file mode 100644 index 000000000..c22960a71 --- /dev/null +++ b/sys/lib/libsa/globals.c @@ -0,0 +1,27 @@ +/* $NetBSD: globals.c,v 1.8 2008/11/19 12:36:41 ad Exp $ */ + +/* + * globals.c: + * + * global variables should be separate, so nothing else + * must be included extraneously. + */ + +#include +#include +#include + +#include "stand.h" +#include "net.h" + +u_char bcea[6] = BA; /* broadcast ethernet address */ + +char rootpath[FNAME_SIZE]; /* root mount path */ +char bootfile[FNAME_SIZE]; /* bootp says to boot this */ +char hostname[FNAME_SIZE]; /* our hostname */ +char *fsmod = "ffs"; /* guessed file system module name */ +char *fsmod2; /* a requisite module */ +struct in_addr myip; /* my ip address */ +struct in_addr rootip; /* root ip address */ +struct in_addr gateip; /* swap ip address */ +n_long netmask = 0xffffff00; /* subnet or net mask */ diff --git a/sys/lib/libsa/ioctl.c b/sys/lib/libsa/ioctl.c new file mode 100644 index 000000000..85b514a15 --- /dev/null +++ b/sys/lib/libsa/ioctl.c @@ -0,0 +1,88 @@ +/* $NetBSD: ioctl.c,v 1.11 2007/12/02 04:59:25 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ioctl.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +int +ioctl(int fd, u_long cmd, char *arg) +{ +#if !defined(LIBSA_NO_FD_CHECKING) || !defined(LIBSA_NO_RAW_ACCESS) + struct open_file *f = &files[fd]; +#endif + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + return -1; + } +#endif +#if !defined(LIBSA_NO_RAW_ACCESS) + if (f->f_flags & F_RAW) { + errno = DEV_IOCTL(f->f_dev)(f, cmd, arg); + if (errno) + return -1; + return 0; + } +#endif + errno = EIO; + return -1; +} diff --git a/sys/lib/libsa/iodesc.h b/sys/lib/libsa/iodesc.h new file mode 100644 index 000000000..884651e9c --- /dev/null +++ b/sys/lib/libsa/iodesc.h @@ -0,0 +1,77 @@ +/* $NetBSD: iodesc.h,v 1.9 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __SYS_LIBNETBOOT_IODESC_H +#define __SYS_LIBNETBOOT_IODESC_H + +#ifdef _STANDALONE +/* + * libsa code uses the following types to avoid 64 bit time_t: + * + * satime_t: + * numbers in seconds returned by the machine dependent getsecs() function + * which are used to measure relative time + * + * saseconds_t: + * numbers in seconds used to specify timeout to network drivers + * + */ +typedef unsigned int satime_t; +typedef int saseconds_t; +#else +typedef time_t satime_t; +typedef time_t saseconds_t; +#endif + +struct iodesc { + struct in_addr destip; /* dest. ip addr, net order */ + struct in_addr myip; /* local ip addr, net order */ + u_short destport; /* dest. port, net order */ + u_short myport; /* local port, net order */ + u_long xid; /* transaction identification */ + u_char myea[6]; /* my ethernet address */ + void *io_netif; +}; + +struct iodesc *socktodesc(int); +ssize_t netif_get(struct iodesc *, void *, size_t, saseconds_t); +ssize_t netif_put(struct iodesc *, void *, size_t); + +#endif /* __SYS_LIBNETBOOT_IODESC_H */ diff --git a/sys/lib/libsa/ip.c b/sys/lib/libsa/ip.c new file mode 100644 index 000000000..50aee4df1 --- /dev/null +++ b/sys/lib/libsa/ip.c @@ -0,0 +1,190 @@ +/* $NetBSD: ip.c,v 1.2 2011/05/13 23:35:09 nakayama Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * Copyright (c) 2010 Zoltan Arnold NAGY + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "net.h" + +/* + * sends an IP packet, if it's alredy constructed +*/ +static ssize_t +_sendip(struct iodesc * d, struct ip * ip, size_t len) +{ + u_char *ea; + + if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || + netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) { + ea = arpwhohas(d, ip->ip_dst); + } else { + ea = arpwhohas(d, gateip); + } + + return sendether(d, ip, len, ea, ETHERTYPE_IP); +} + +/* + * fills out the IP header + * Caller must leave room for ethernet, ip and udp headers in front! +*/ +ssize_t +sendip(struct iodesc * d, void *pkt, size_t len, u_int8_t proto) +{ + ssize_t cc; + struct ip *ip; + + ip = (struct ip *) pkt - 1; + len += sizeof(*ip); + + (void) memset(ip, 0, sizeof(*ip)); + + ip->ip_v = IPVERSION; + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_len = htons(len); + ip->ip_p = proto; + ip->ip_ttl = IPDEFTTL; + ip->ip_src = d->myip; + ip->ip_dst = d->destip; + ip->ip_sum = ip_cksum(ip, sizeof(*ip)); + + cc = _sendip(d, ip, len); + + if (cc == -1) + return -1; + if ((size_t) cc != len) + panic("sendip: bad write (%zd != %zu)", cc, len); + return (cc - (sizeof(*ip))); +} + +/* + * reads an IP packet + * WARNING: the old version stripped the IP options, if there were + * any. Because we have absolutely no idea if the upper layer needs + * these or not, it's best to leave them there. + * + * The size returned is the size indicated in the header. + */ +ssize_t +readip(struct iodesc * d, void *pkt, size_t len, time_t tleft, u_int8_t proto) +{ + ssize_t n; + size_t hlen; + struct ip *ip; + u_int16_t etype; + + ip = (struct ip *) pkt - 1; + + n = readether(d, ip, len + sizeof(*ip), tleft, &etype); + if (n == -1 || (size_t) n < sizeof(*ip)) + return -1; + + if (etype == ETHERTYPE_ARP) { + struct arphdr *ah = (void *) ip; + if (ah->ar_op == htons(ARPOP_REQUEST)) { + /* Send ARP reply */ + arp_reply(d, ah); + } + return -1; + } + + if (etype != ETHERTYPE_IP) { +#ifdef NET_DEBUG + if (debug) + printf("readip: not IP. ether_type=%x\n", etype); +#endif + return -1; + } + + /* Check ip header */ + if (ip->ip_v != IPVERSION || + ip->ip_p != proto) { /* half char */ +#ifdef NET_DEBUG + if (debug) { + printf("readip: wrong IP version or wrong proto " + "ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p); + } +#endif + return -1; + } + + hlen = ip->ip_hl << 2; + if (hlen < sizeof(*ip) || ip_cksum(ip, hlen) != 0) { +#ifdef NET_DEBUG + if (debug) + printf("readip: short hdr or bad cksum.\n"); +#endif + return -1; + } + if (n < ntohs(ip->ip_len)) { +#ifdef NET_DEBUG + if (debug) + printf("readip: bad length %d < %d.\n", + (int) n, ntohs(ip->ip_len)); +#endif + return -1; + } + if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { +#ifdef NET_DEBUG + if (debug) { + printf("readip: bad saddr %s != ", inet_ntoa(d->myip)); + printf("%s\n", inet_ntoa(ip->ip_dst)); + } +#endif + return -1; + } + return (ntohs(ip->ip_len) - 20); +} diff --git a/sys/lib/libsa/ip_cksum.c b/sys/lib/libsa/ip_cksum.c new file mode 100644 index 000000000..429416b73 --- /dev/null +++ b/sys/lib/libsa/ip_cksum.c @@ -0,0 +1,106 @@ +/* $NetBSD: ip_cksum.c,v 1.2 2006/01/25 13:46:09 christos Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: in_cksum.c,v 1.1 92/09/11 01:15:55 leres Exp (LBL) + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "stand.h" +#include "net.h" + +/* + * Checksum routine for Internet Protocol family headers. + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + * In particular, it should not be this one. + */ +int +ip_cksum(const void *p, size_t llen) +{ + int sum = 0, oddbyte = 0, v = 0, len = (int)llen; + const u_char *cp = p; + + /* we assume < 2^16 bytes being summed */ + while (len > 0) { + if (oddbyte) { + sum += v + *cp++; + len--; + } + if (((long)cp & 1) == 0) { + while ((len -= 2) >= 0) { + sum += *(const u_short *)cp; + cp += 2; + } + } else { + while ((len -= 2) >= 0) { +#if BYTE_ORDER == BIG_ENDIAN + sum += *cp++ << 8; + sum += *cp++; +#else + sum += *cp++; + sum += *cp++ << 8; +#endif + } + } + if ((oddbyte = len & 1) != 0) +#if BYTE_ORDER == BIG_ENDIAN + v = *cp << 8; +#else + v = *cp; +#endif + } + if (oddbyte) + sum += v; + sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */ + sum += sum >> 16; /* add potential last carry */ + return (0xffff & ~sum); +} diff --git a/sys/lib/libsa/lfs.h b/sys/lib/libsa/lfs.h new file mode 100644 index 000000000..3698afb49 --- /dev/null +++ b/sys/lib/libsa/lfs.h @@ -0,0 +1,35 @@ +/* $NetBSD: lfs.h,v 1.5 2005/12/11 12:24:46 christos Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs.h 8.1 (Berkeley) 6/11/93 + */ + +FS_DEF(lfsv1); +FS_DEF(lfsv2); diff --git a/sys/lib/libsa/lfsv1.c b/sys/lib/libsa/lfsv1.c new file mode 100644 index 000000000..7dfc10735 --- /dev/null +++ b/sys/lib/libsa/lfsv1.c @@ -0,0 +1,25 @@ +/* $NetBSD: lfsv1.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */ + +#define LIBSA_LFS +#define REQUIRED_LFS_VERSION 1 + +#define ufs_open lfsv1_open +#define ufs_close lfsv1_close +#define ufs_read lfsv1_read +#define ufs_write lfsv1_write +#define ufs_seek lfsv1_seek +#define ufs_stat lfsv1_stat +#if defined(LIBSA_ENABLE_LS_OP) +#define ufs_ls lfsv1_ls +#endif + +#define fs_bsize lfs_ibsize +#define IFILE_Vx IFILE_V1 + +#define FSBTODB(fs, daddr) (daddr) /* LFSv1 uses sectors for addresses */ +#define INOPBx(fs) INOPB(fs) + +#define FSMOD "lfs" +#define FSMOD2 "ffs" + +#include "lib/libsa/ufs.c" diff --git a/sys/lib/libsa/lfsv2.c b/sys/lib/libsa/lfsv2.c new file mode 100644 index 000000000..498a9389b --- /dev/null +++ b/sys/lib/libsa/lfsv2.c @@ -0,0 +1,28 @@ +/* $NetBSD: lfsv2.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */ + +#define LIBSA_LFS +#define REQUIRED_LFS_VERSION 2 + +#define ufs_open lfsv2_open +#define ufs_close lfsv2_close +#define ufs_read lfsv2_read +#define ufs_write lfsv2_write +#define ufs_seek lfsv2_seek +#define ufs_stat lfsv2_stat +#if defined(LIBSA_ENABLE_LS_OP) +#define ufs_ls lfsv2_ls +#endif + +#define fs_bsize lfs_bsize +#define IFILE_Vx IFILE + +#ifdef LFS_IFILE_FRAG_ADDRESSING /* XXX see sys/ufs/lfs/ -- not tested */ +#define INOPBx(fs) INOPF(fs) +#else +#define INOPBx(fs) INOPB(fs) +#endif + +#define FSMOD "lfs" +#define FSMOD2 "ffs" + +#include "lib/libsa/ufs.c" diff --git a/sys/lib/libsa/loadfile.c b/sys/lib/libsa/loadfile.c new file mode 100644 index 000000000..b4fce236a --- /dev/null +++ b/sys/lib/libsa/loadfile.c @@ -0,0 +1,194 @@ +/* $NetBSD: loadfile.c,v 1.30 2008/05/20 16:04:08 ad Exp $ */ + +/*- + * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +#ifdef _STANDALONE +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +#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 : "")); + return -1; + } + + /* Load it; save the value of errno across the close() call */ + if ((error = fdloadfile(fd, marks, flags)) != 0) { + (void)close(fd); + errno = error; + return -1; + } + + return fd; +} + +/* + * Read in program from the given file descriptor. + * Return error code (0 on success). + * Fill in marks. + */ +int +fdloadfile(int fd, u_long *marks, int flags) +{ + union { +#ifdef BOOT_ECOFF + struct ecoff_exechdr coff; +#endif +#ifdef BOOT_ELF32 + Elf32_Ehdr elf32; +#endif +#ifdef BOOT_ELF64 + Elf64_Ehdr elf64; +#endif +#ifdef BOOT_AOUT + struct exec aout; +#endif + } hdr; + ssize_t nr; + int rval; + + /* Read the exec header. */ + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) + goto err; + nr = read(fd, &hdr, sizeof(hdr)); + if (nr == -1) { + WARN(("read header failed")); + goto err; + } + if (nr != sizeof(hdr)) { + WARN(("read header short")); + errno = EFTYPE; + goto err; + } + +#ifdef BOOT_ECOFF + if (!ECOFF_BADMAG(&hdr.coff)) { + rval = loadfile_coff(fd, &hdr.coff, marks, flags); + } else +#endif +#ifdef BOOT_ELF32 + if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { + netbsd_elf_class = ELFCLASS32; + rval = loadfile_elf32(fd, &hdr.elf32, marks, flags); + } else +#endif +#ifdef BOOT_ELF64 + if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 && + hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) { + netbsd_elf_class = ELFCLASS64; + rval = loadfile_elf64(fd, &hdr.elf64, marks, flags); + } else +#endif +#ifdef BOOT_AOUT + if (OKMAGIC(N_GETMAGIC(hdr.aout)) +#ifndef NO_MID_CHECK + && N_GETMID(hdr.aout) == MID_MACHINE +#endif + ) { + rval = loadfile_aout(fd, &hdr.aout, marks, flags); + } else +#endif + { + rval = 1; + errno = EFTYPE; + } + + if (rval == 0) { + if ((flags & LOAD_ALL) != 0) + PROGRESS(("=0x%lx\n", + marks[MARK_END] - marks[MARK_START])); + return 0; + } +err: + return errno; +} diff --git a/sys/lib/libsa/loadfile.h b/sys/lib/libsa/loadfile.h new file mode 100644 index 000000000..44af4235f --- /dev/null +++ b/sys/lib/libsa/loadfile.h @@ -0,0 +1,94 @@ +/* $NetBSD: loadfile.h,v 1.12 2010/08/25 16:30:01 christos Exp $ */ + +/*- + * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Array indices in the u_long position array + */ +#define MARK_START 0 +#define MARK_ENTRY 1 +#define MARK_DATA 2 +#define MARK_NSYM 3 +#define MARK_SYM 4 +#define MARK_END 5 +#define MARK_MAX 6 + +/* + * Bit flags for sections to load + */ +#define LOAD_TEXT 0x0001 +#define LOAD_TEXTA 0x0002 +#define LOAD_DATA 0x0004 +#define LOAD_BSS 0x0008 +#define LOAD_SYM 0x0010 +#define LOAD_HDR 0x0020 +#define LOAD_NOTE 0x0040 +#define LOAD_ALL 0x007f +#define LOAD_MINIMAL 0x002f +#define LOAD_BACKWARDS 0x0050 + +#define COUNT_TEXT 0x0100 +#define COUNT_TEXTA 0x0200 +#define COUNT_DATA 0x0400 +#define COUNT_BSS 0x0800 +#define COUNT_SYM 0x1000 +#define COUNT_HDR 0x2000 +#define COUNT_ALL 0x3f00 + +int loadfile(const char *, u_long *, int); +int fdloadfile(int fd, u_long *, int); + +#ifndef MACHINE_LOADFILE_MACHDEP +#define MACHINE_LOADFILE_MACHDEP "machine/loadfile_machdep.h" +#endif +#include MACHINE_LOADFILE_MACHDEP + +#ifdef BOOT_ECOFF +#include +int loadfile_coff(int, struct ecoff_exechdr *, u_long *, int); +#endif + +#if defined(BOOT_ELF32) || defined(BOOT_ELF64) +#include +#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 +int loadfile_aout(int, struct exec *, u_long *, int); +#endif + +extern uint32_t netbsd_version; +extern u_int netbsd_elf_class; diff --git a/sys/lib/libsa/loadfile_aout.c b/sys/lib/libsa/loadfile_aout.c new file mode 100644 index 000000000..eb395e87e --- /dev/null +++ b/sys/lib/libsa/loadfile_aout.c @@ -0,0 +1,304 @@ +/* $NetBSD: loadfile_aout.c,v 1.14 2009/08/16 13:26:16 matt Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)boot.c 8.1 (Berkeley) 6/10/93 + */ + +#ifdef _STANDALONE +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +#include "loadfile.h" + +#ifdef BOOT_AOUT + +int +loadfile_aout(int fd, struct exec *x, u_long *marks, int flags) +{ + u_long entry = x->a_entry; + paddr_t aoutp = 0; + paddr_t minp, maxp; + int cc; + paddr_t offset = marks[MARK_START]; + u_long magic = N_GETMAGIC(*x); + int sub; + ssize_t nr; + + /* some ports dont use the offset */ + offset = offset; + + /* In OMAGIC and NMAGIC, exec header isn't part of text segment */ + if (magic == OMAGIC || magic == NMAGIC) + sub = 0; + else + sub = sizeof(*x); + + minp = maxp = ALIGNENTRY(entry); + + if (lseek(fd, sizeof(*x), SEEK_SET) == -1) { + WARN(("lseek text")); + return 1; + } + + /* + * Leave a copy of the exec header before the text. + * The kernel may use this to verify that the + * symbols were loaded by this boot program. + */ + if (magic == OMAGIC || magic == NMAGIC) { + if (flags & LOAD_HDR && maxp >= sizeof(*x)) + BCOPY(x, maxp - sizeof(*x), sizeof(*x)); + } + else { + if (flags & LOAD_HDR) + BCOPY(x, maxp, sizeof(*x)); + if (flags & (LOAD_HDR|COUNT_HDR)) + maxp += sizeof(*x); + } + + /* + * Read in the text segment. + */ + if (flags & LOAD_TEXT) { + PROGRESS(("%ld", x->a_text)); + + nr = READ(fd, maxp, x->a_text - sub); + if (nr == -1) { + WARN(("read text")); + return 1; + } + if (nr != (ssize_t)(x->a_text - sub)) { + errno = EIO; + WARN(("read text")); + return 1; + } + } else { + if (lseek(fd, x->a_text - sub, SEEK_CUR) == -1) { + WARN(("seek text")); + return 1; + } + } + if (flags & (LOAD_TEXT|COUNT_TEXT)) + maxp += x->a_text - sub; + + /* + * Provide alignment if required + */ + if (magic == ZMAGIC || magic == NMAGIC) { + int size = -(unsigned int)maxp & (AOUT_LDPGSZ - 1); + + if (flags & LOAD_TEXTA) { + PROGRESS(("/%d", size)); + BZERO(maxp, size); + } + + if (flags & (LOAD_TEXTA|COUNT_TEXTA)) + maxp += size; + } + + /* + * Read in the data segment. + */ + if (flags & LOAD_DATA) { + PROGRESS(("+%ld", x->a_data)); + + marks[MARK_DATA] = LOADADDR(maxp); + nr = READ(fd, maxp, x->a_data); + if (nr == -1) { + WARN(("read data")); + return 1; + } + if (nr != (ssize_t)x->a_data) { + errno = EIO; + WARN(("read data")); + return 1; + } + } + else { + if (lseek(fd, x->a_data, SEEK_CUR) == -1) { + WARN(("seek data")); + return 1; + } + } + if (flags & (LOAD_DATA|COUNT_DATA)) + maxp += x->a_data; + + /* + * Zero out the BSS section. + * (Kernel doesn't care, but do it anyway.) + */ + if (flags & LOAD_BSS) { + PROGRESS(("+%ld", x->a_bss)); + + BZERO(maxp, x->a_bss); + } + + if (flags & (LOAD_BSS|COUNT_BSS)) + maxp += x->a_bss; + + /* + * Read in the symbol table and strings. + * (Always set the symtab size word.) + */ + if (flags & LOAD_SYM) + BCOPY(&x->a_syms, maxp, sizeof(x->a_syms)); + + if (flags & (LOAD_SYM|COUNT_SYM)) { + maxp += sizeof(x->a_syms); + aoutp = maxp; + } + + if (x->a_syms > 0) { + /* Symbol table and string table length word. */ + + if (flags & LOAD_SYM) { + PROGRESS(("+[%ld", x->a_syms)); + + nr = READ(fd, maxp, x->a_syms); + if (nr == -1) { + WARN(("read symbols")); + return 1; + } + if (nr != (ssize_t)x->a_syms) { + errno = EIO; + WARN(("read symbols")); + return 1; + } + } else { + if (lseek(fd, x->a_syms, SEEK_CUR) == -1) { + WARN(("seek symbols")); + return 1; + } + } + if (flags & (LOAD_SYM|COUNT_SYM)) + maxp += x->a_syms; + + nr = read(fd, &cc, sizeof(cc)); + if (nr == -1) { + WARN(("read string table")); + return 1; + } + if (nr != sizeof(cc)) { + errno = EIO; + WARN(("read string table")); + return 1; + } + + if (flags & LOAD_SYM) { + BCOPY(&cc, maxp, sizeof(cc)); + + /* String table. Length word includes itself. */ + + PROGRESS(("+%d]", cc)); + } + if (flags & (LOAD_SYM|COUNT_SYM)) + maxp += sizeof(cc); + + cc -= sizeof(int); + if (cc <= 0) { + WARN(("symbol table too short")); + return 1; + } + + if (flags & LOAD_SYM) { + nr = READ(fd, maxp, cc); + if (nr == -1) { + WARN(("read strings")); + return 1; + } + if (nr != cc) { + errno = EIO; + WARN(("read strings")); + return 1; + } + } else { + if (lseek(fd, cc, SEEK_CUR) == -1) { + WARN(("seek strings")); + return 1; + } + } + if (flags & (LOAD_SYM|COUNT_SYM)) + maxp += cc; + } + + marks[MARK_START] = LOADADDR(minp); + marks[MARK_ENTRY] = LOADADDR(entry); + marks[MARK_NSYM] = x->a_syms; + marks[MARK_SYM] = LOADADDR(aoutp); + marks[MARK_END] = LOADADDR(maxp); + return 0; +} + +#endif /* BOOT_AOUT */ diff --git a/sys/lib/libsa/loadfile_ecoff.c b/sys/lib/libsa/loadfile_ecoff.c new file mode 100644 index 000000000..73155d741 --- /dev/null +++ b/sys/lib/libsa/loadfile_ecoff.c @@ -0,0 +1,147 @@ +/* $NetBSD: loadfile_ecoff.c,v 1.12 2008/04/28 20:24:06 martin Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _STANDALONE +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +#include "loadfile.h" + +#ifdef BOOT_ECOFF + +int +loadfile_coff(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags) +{ + paddr_t offset = marks[MARK_START]; + paddr_t minp = ~0, maxp = 0, pos; + ssize_t nr; + + /* some ports dont use the offset */ + offset = offset; + + /* Read in text. */ + if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1) { + WARN(("lseek text")); + return 1; + } + + if (coff->a.tsize != 0) { + if (flags & LOAD_TEXT) { + PROGRESS(("%lu", coff->a.tsize)); + nr = READ(fd, coff->a.text_start, coff->a.tsize); + if (nr == -1) { + return 1; + } + if (nr != coff->a.tsize) { + errno = EIO; + return 1; + } + } + else { + if (lseek(fd, coff->a.tsize, SEEK_CUR) == -1) { + WARN(("read text")); + return 1; + } + } + if (flags & (COUNT_TEXT|LOAD_TEXT)) { + pos = coff->a.text_start; + if (minp > pos) + minp = pos; + pos += coff->a.tsize; + if (maxp < pos) + maxp = pos; + } + } + + /* Read in data. */ + if (coff->a.dsize != 0) { + if (flags & LOAD_DATA) { + PROGRESS(("+%lu", coff->a.dsize)); + nr = READ(fd, coff->a.data_start, coff->a.dsize); + if (nr == -1) { + WARN(("read data")); + return 1; + } + if (nr != coff->a.dsize) { + errno = EIO; + WARN(("read data")); + return 1; + } + } + if (flags & (COUNT_DATA|LOAD_DATA)) { + pos = coff->a.data_start; + if (minp > pos) + minp = pos; + pos += coff->a.dsize; + if (maxp < pos) + maxp = pos; + } + } + + /* Zero out bss. */ + if (coff->a.bsize != 0) { + if (flags & LOAD_BSS) { + PROGRESS(("+%lu", coff->a.bsize)); + BZERO(coff->a.bss_start, coff->a.bsize); + } + if (flags & (COUNT_BSS|LOAD_BSS)) { + pos = coff->a.bss_start; + if (minp > pos) + minp = pos; + pos = coff->a.bsize; + if (maxp < pos) + maxp = pos; + } + } + + marks[MARK_START] = LOADADDR(minp); + marks[MARK_ENTRY] = LOADADDR(coff->a.entry); + marks[MARK_NSYM] = 1; /* XXX: Kernel needs >= 0 */ + marks[MARK_SYM] = LOADADDR(maxp); + marks[MARK_END] = LOADADDR(maxp); + marks[MARK_DATA] = LOADADDR(coff->a.data_start); + return 0; +} + +#endif /* BOOT_ECOFF */ diff --git a/sys/lib/libsa/loadfile_elf32.c b/sys/lib/libsa/loadfile_elf32.c new file mode 100644 index 000000000..1418e8f92 --- /dev/null +++ b/sys/lib/libsa/loadfile_elf32.c @@ -0,0 +1,625 @@ +/* $NetBSD: loadfile_elf32.c,v 1.29 2011/02/17 21:15:31 christos Exp $ */ + +/*- + * Copyright (c) 1997, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* If not included by exec_elf64.c, ELFSIZE won't be defined. */ +#ifndef ELFSIZE +#define ELFSIZE 32 +#endif + +#ifdef _STANDALONE +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +#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 +#include +#include +#include +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 \n", getprogname()); + return 1; + } + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(1, "Can't open `%s'", argv[1]); + if (read(fd, &elf, sizeof(elf)) != sizeof(elf)) + err(1, "Can't read `%s'", argv[1]); + memset(marks, 0, sizeof(marks)); + marks[MARK_START] = (u_long)malloc(2LL * 1024 * 2024 * 1024); + ELFNAMEEND(loadfile)(fd, &elf, marks, LOAD_ALL); + printf("%d\n", netbsd_version); + return 0; +} +#endif + +#endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ diff --git a/sys/lib/libsa/loadfile_elf64.c b/sys/lib/libsa/loadfile_elf64.c new file mode 100644 index 000000000..28a67cd23 --- /dev/null +++ b/sys/lib/libsa/loadfile_elf64.c @@ -0,0 +1,40 @@ +/* $NetBSD: loadfile_elf64.c,v 1.1 2001/10/31 17:20:50 thorpej Exp $ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define ELFSIZE 64 + +#include "loadfile_elf32.c" diff --git a/sys/lib/libsa/lookup_elf32.c b/sys/lib/libsa/lookup_elf32.c new file mode 100644 index 000000000..46dd4b6c5 --- /dev/null +++ b/sys/lib/libsa/lookup_elf32.c @@ -0,0 +1,96 @@ +/* $NetBSD: lookup_elf32.c,v 1.3 2010/02/11 21:28:16 martin Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* If not included by lookup_elf64.c, ELFSIZE won't be defined. */ +#ifndef ELFSIZE +#define ELFSIZE 32 +#endif + +#include +#include +#include + +#if ((ELFSIZE == 32) && defined(BOOT_ELF32)) || \ + ((ELFSIZE == 64) && defined(BOOT_ELF64)) + +void * ELFNAMEEND(lookup_symbol)(const char *, void *, void *); + +void * +ELFNAMEEND(lookup_symbol)(const char *symname, void *sstab, void *estab) +{ + Elf_Ehdr *elf; + Elf_Shdr *shp; + Elf_Sym *symtab_start, *symtab_end, *sp; + char *strtab_start, *strtab_end; + int i, j; + + elf = sstab; + if (elf->e_shoff == 0) + return NULL; + + switch (elf->e_machine) { + ELFDEFNNAME(MACHDEP_ID_CASES) + default: + return NULL; + } + + symtab_start = symtab_end = NULL; + strtab_start = strtab_end = NULL; + + shp = (Elf_Shdr *)((char *)sstab + elf->e_shoff); + for (i = 0; i < elf->e_shnum; i++) { + if (shp[i].sh_type != SHT_SYMTAB) + continue; + if (shp[i].sh_offset == 0) + continue; + symtab_start = (Elf_Sym*)((char*)sstab + shp[i].sh_offset); + symtab_end = (Elf_Sym*)((char*)sstab + shp[i].sh_offset + + shp[i].sh_size); + j = shp[i].sh_link; + if (shp[j].sh_offset == 0) + continue; + strtab_start = (char*)sstab + shp[j].sh_offset; + strtab_end = (char*)sstab + shp[j].sh_offset + shp[j].sh_size; + break; + } + + if (!symtab_start || !strtab_start) + return NULL; + + for (sp = symtab_start; sp < symtab_end; sp++) + if (sp->st_name != 0 && + strcmp(strtab_start + sp->st_name, symname) == 0) + return (void*)(uintptr_t)sp->st_value; + + return NULL; +} + +#endif /* (ELFSIZE == 32 && BOOT_ELF32) || (ELFSIZE == 64 && BOOT_ELF64) */ diff --git a/sys/lib/libsa/lookup_elf64.c b/sys/lib/libsa/lookup_elf64.c new file mode 100644 index 000000000..24b539917 --- /dev/null +++ b/sys/lib/libsa/lookup_elf64.c @@ -0,0 +1,33 @@ +/* $NetBSD: lookup_elf64.c,v 1.1 2010/02/10 21:54:47 martin Exp $ */ +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#define ELFSIZE 64 + +#include "lookup_elf32.c" diff --git a/sys/lib/libsa/ls.c b/sys/lib/libsa/ls.c new file mode 100644 index 000000000..dbed957da --- /dev/null +++ b/sys/lib/libsa/ls.c @@ -0,0 +1,161 @@ +/* $NetBSD: ls.c,v 1.3 2011/12/25 06:09:08 tsutsui Exp $ */ + +/*- + * Copyright (c) 2011 + * The NetBSD Foundation, Inc. All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Martin Husemann. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "stand.h" +#include +#include + +void +ls(const char *path) +{ + int fd; + struct stat sb; + size_t size; + const char *fname = 0; + char *p; + struct open_file *f; + + if ((fd = open(path, 0)) < 0 + || fstat(fd, &sb) < 0 + || (sb.st_mode & S_IFMT) != S_IFDIR) { + /* Path supplied isn't a directory, open parent + directory and list matching files. */ + if (fd >= 0) + close(fd); + fname = strrchr(path, '/'); + if (fname) { + size = fname - path; + p = alloc(size + 1); + if (!p) + goto out; + memcpy(p, path, size); + p[size] = 0; + fd = open(p, 0); + dealloc(p, size + 1); + } else { + fd = open("", 0); + fname = path; + } + + if (fd < 0) { + printf("ls: %s\n", strerror(errno)); + return; + } + if (fstat(fd, &sb) < 0) { + printf("stat: %s\n", strerror(errno)); + goto out; + } + if ((sb.st_mode & S_IFMT) != S_IFDIR) { + printf("%s: %s\n", path, strerror(ENOTDIR)); + goto out; + } + } + + f = &files[fd]; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + goto out; + } +#endif + +#if !defined(LIBSA_NO_RAW_ACCESS) + /* operation not defined on raw devices */ + if (f->f_flags & F_RAW) { + errno = EOPNOTSUPP; + goto out; + } +#endif + + if (FS_LS(f->f_ops) != NULL) + FS_LS(f->f_ops)(f, fname); + else + printf("no ls support for this file system\n"); + +out: + close(fd); +} diff --git a/sys/lib/libsa/lseek.c b/sys/lib/libsa/lseek.c new file mode 100644 index 000000000..eb3f22f11 --- /dev/null +++ b/sys/lib/libsa/lseek.c @@ -0,0 +1,103 @@ +/* $NetBSD: lseek.c,v 1.11 2007/12/02 04:59:26 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lseek.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +off_t +#ifndef __INTERNAL_LIBSA_CREAD +lseek(int fd, off_t offset, int where) +#else +olseek(int fd, off_t offset, int where) +#endif +{ + struct open_file *f = &files[fd]; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) { + errno = EBADF; + return -1; + } +#endif + +#if !defined(LIBSA_NO_RAW_ACCESS) + if (f->f_flags & F_RAW) { + /* + * On RAW devices, update internal offset. + */ + switch (where) { + case SEEK_SET: + f->f_offset = offset; + break; + case SEEK_CUR: + f->f_offset += offset; + break; + case SEEK_END: + default: + errno = EOFFSET; + return -1; + } + return f->f_offset; + } +#endif + + return FS_SEEK(f->f_ops)(f, offset, where); +} diff --git a/sys/lib/libsa/minixfs3.c b/sys/lib/libsa/minixfs3.c new file mode 100644 index 000000000..a72217302 --- /dev/null +++ b/sys/lib/libsa/minixfs3.c @@ -0,0 +1,991 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2012 + * Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved. + * + * Author: Evgeniy Ivanov (based on libsa/ext2fs.c). + * + * This code is derived from src/sys/lib/libsa/ext2fs.c contributed to + * The NetBSD Foundation, see copyrights below. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997 Manuel Bouyer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Copyright (c) 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: David Golub + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Stand-alone file reading package for MFS file system. + */ + +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "minixfs3.h" + +#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK) +#define LIBSA_NO_FS_SYMLINK +#endif + +#if defined(LIBSA_NO_TWIDDLE) +#define twiddle() +#endif + +typedef uint32_t ino32_t; +#ifndef FSBTODB +#define FSBTODB(fs, indp) fsbtodb(fs, indp) +#endif + +/* + * To avoid having a lot of filesystem-block sized buffers lurking (which + * could be 32k) we only keep a few entries of the indirect block map. + * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block + * ~13 times pulling in a 6M kernel. + * The cache size must be smaller than the smallest filesystem block, + * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks). + */ +#define LN2_IND_CACHE_SZ 6 +#define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ) +#define IND_CACHE_MASK (IND_CACHE_SZ - 1) + +/* + * In-core open file. + */ +struct file { + off_t f_seekp; /* seek pointer */ + struct mfs_sblock *f_fs; /* pointer to super-block */ + struct mfs_dinode f_di; /* copy of on-disk inode */ + uint f_nishift; /* for blocks in indirect block */ + block_t f_ind_cache_block; + block_t f_ind_cache[IND_CACHE_SZ]; + + char *f_buf; /* buffer for data block */ + size_t f_buf_size; /* size of data block */ + daddr_t f_buf_blkno; /* block number of data block */ +}; + +#if defined(LIBSA_ENABLE_LS_OP) + +#define NELEM(x) (sizeof (x) / sizeof(*x)) + +typedef struct entry_t entry_t; +struct entry_t { + entry_t *e_next; + ino32_t e_ino; + char e_name[1]; +}; + +static int +fn_match(const char *fname, const char *pattern) +{ + char fc, pc; + + do { + fc = *fname++; + pc = *pattern++; + if (!fc && !pc) + return 1; + if (pc == '?' && fc) + pc = fc; + } while (fc == pc); + + if (pc != '*') + return 0; + /* + * Too hard (and unnecessary really) too check for "*?name" etc.... + * "**" will look for a '*' and "*?" a '?' + */ + pc = *pattern++; + if (!pc) + return 1; + while ((fname = strchr(fname, pc))) + if (fn_match(++fname, pattern)) + return 1; + return 0; +} +#endif /* LIBSA_ENABLE_LS_OP */ + + +static int read_inode(ino32_t, struct open_file *); +static int block_map(struct open_file *, block_t, block_t *); +static int buf_read_file(struct open_file *, char **, size_t *); +static int search_directory(const char *, int, struct open_file *, ino32_t *); +static int read_sblock(struct open_file *, struct mfs_sblock *); + +/* + * Read a new inode into a file structure. + */ +static int +read_inode(ino32_t inumber, struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct mfs_sblock *fs = fp->f_fs; + char *buf; + size_t rsize; + int rc; + daddr_t inode_sector; + struct mfs_dinode *dip; + + inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); + + /* + * Read inode and save it. + */ + buf = fp->f_buf; + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + inode_sector, fs->mfs_block_size, buf, &rsize); + if (rc) + return rc; + if (rsize != fs->mfs_block_size) + return EIO; + + dip = (struct mfs_dinode *)(buf + + INODE_SIZE * ino_to_fsbo(fs, inumber)); + mfs_iload(dip, &fp->f_di); + + /* + * Clear out the old buffers + */ + fp->f_ind_cache_block = ~0; + fp->f_buf_blkno = -1; + return rc; +} + +/* + * Given an offset in a file, find the disk block number (not zone!) + * that contains that block. + */ +static int +block_map(struct open_file *f, block_t file_block, block_t *disk_block_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct mfs_sblock *fs = fp->f_fs; + uint level; + block_t ind_cache; + block_t ind_block_num; + zone_t zone; + size_t rsize; + int rc; + int boff; + int scale = fs->mfs_log_zone_size; /* for block-zone conversion */ + block_t *buf = (void *)fp->f_buf; + + /* + * Index structure of an inode: + * + * mdi_blocks[0..NR_DZONES-1] + * hold zone numbers for zones + * 0..NR_DZONES-1 + * + * mdi_blocks[NR_DZONES+0] + * block NDADDR+0 is the single indirect block + * holds zone numbers for zones + * NR_DZONES .. NR_DZONES + NINDIR(fs)-1 + * + * mdi_blocks[NR_DZONES+1] + * block NDADDR+1 is the double indirect block + * holds zone numbers for INDEX blocks for zones + * NR_DZONES + NINDIR(fs) .. + * NR_TZONES + NINDIR(fs) + NINDIR(fs)**2 - 1 + */ + + zone = file_block >> scale; + boff = (int) (file_block - (zone << scale) ); /* relative blk in zone */ + + if (zone < NR_DZONES) { + /* Direct zone */ + zone_t z = fs2h32(fp->f_di.mdi_zone[zone]); + if (z == NO_ZONE) { + *disk_block_p = NO_BLOCK; + return 0; + } + *disk_block_p = (block_t) ((z << scale) + boff); + return 0; + } + + zone -= NR_DZONES; + + ind_cache = zone >> LN2_IND_CACHE_SZ; + if (ind_cache == fp->f_ind_cache_block) { + *disk_block_p = + fs2h32(fp->f_ind_cache[zone & IND_CACHE_MASK]); + return 0; + } + + for (level = 0;;) { + level += fp->f_nishift; + + if (zone < (block_t)1 << level) + break; + if (level > NIADDR * fp->f_nishift) + /* Zone number too high */ + return EFBIG; + zone -= (block_t)1 << level; + } + + ind_block_num = + fs2h32(fp->f_di.mdi_zone[NR_DZONES + (level / fp->f_nishift - 1)]); + + for (;;) { + level -= fp->f_nishift; + if (ind_block_num == 0) { + *disk_block_p = NO_BLOCK; /* missing */ + return 0; + } + + twiddle(); + /* + * If we were feeling brave, we could work out the number + * of the disk sector and read a single disk sector instead + * of a filesystem block. + * However we don't do this very often anyway... + */ + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fs, ind_block_num), fs->mfs_block_size, + buf, &rsize); + if (rc) + return rc; + if (rsize != fs->mfs_block_size) + return EIO; + + ind_block_num = fs2h32(buf[zone >> level]); + if (level == 0) + break; + zone &= (1 << level) - 1; + } + + /* Save the part of the block that contains this sector */ + memcpy(fp->f_ind_cache, &buf[zone & ~IND_CACHE_MASK], + IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); + fp->f_ind_cache_block = ind_cache; + + zone = (zone_t)ind_block_num; + *disk_block_p = (block_t)((zone << scale) + boff); + return 0; +} + +/* + * Read a portion of a file into an internal buffer. + * Return the location in the buffer and the amount in the buffer. + */ +static int +buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct mfs_sblock *fs = fp->f_fs; + long off; + block_t file_block; + block_t disk_block; + size_t block_size; + int rc; + + off = blkoff(fs, fp->f_seekp); + file_block = lblkno(fs, fp->f_seekp); + block_size = fs->mfs_block_size; + + if (file_block != fp->f_buf_blkno) { + rc = block_map(f, file_block, &disk_block); + if (rc) + return rc; + + if (disk_block == 0) { + memset(fp->f_buf, 0, block_size); + fp->f_buf_size = block_size; + } else { + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fs, disk_block), + block_size, fp->f_buf, &fp->f_buf_size); + if (rc) + return rc; + } + + fp->f_buf_blkno = file_block; + } + + /* + * Return address of byte in buffer corresponding to + * offset, and size of remainder of buffer after that + * byte. + */ + *buf_p = fp->f_buf + off; + *size_p = block_size - off; + + /* + * But truncate buffer at end of file. + */ + if (*size_p > fp->f_di.mdi_size - fp->f_seekp) + *size_p = fp->f_di.mdi_size - fp->f_seekp; + + return 0; +} + +/* + * Search a directory for a name and return its + * inode number. + */ +static int +search_directory(const char *name, int length, struct open_file *f, + ino32_t *inumber_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct mfs_sblock *fs = fp->f_fs; + struct mfs_direct *dp; + struct mfs_direct *dbuf; + size_t buf_size; + int namlen; + int rc; + + fp->f_seekp = 0; + + while (fp->f_seekp < (off_t)fp->f_di.mdi_size) { + rc = buf_read_file(f, (char**)&dbuf, &buf_size); + if (rc) + return rc; + if (buf_size == 0) + return EIO; + + /* XXX we assume, that buf_read_file reads an fs block and + * doesn't truncate buffer. Currently i_size in MFS doesn't + * the same as size of allocated blocks, it makes buf_read_file + * to truncate buf_size. + */ + if (buf_size < fs->mfs_block_size) + buf_size = fs->mfs_block_size; + + for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) { + char *cp; + if (fs2h32(dp->mfsd_ino) == (ino32_t) 0) + continue; + /* Compute the length of the name */ + cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name)); + if (cp == NULL) + namlen = sizeof(dp->mfsd_name); + else + namlen = cp - (dp->mfsd_name); + + if (namlen == length && + !memcmp(name, dp->mfsd_name, length)) { + /* found entry */ + *inumber_p = fs2h32(dp->mfsd_ino); + return 0; + } + } + fp->f_seekp += buf_size; + } + return ENOENT; +} + +int +read_sblock(struct open_file *f, struct mfs_sblock *fs) +{ + static uint8_t sbbuf[MINBSIZE]; + size_t buf_size; + int rc; + + /* We must read amount multiple of sector size, hence we can't + * read SBSIZE and read MINBSIZE. + */ + if (SBSIZE > MINBSIZE) + return EINVAL; + + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + SUPER_BLOCK_OFF / DEV_BSIZE, MINBSIZE, sbbuf, &buf_size); + if (rc) + return rc; + + if (buf_size != MINBSIZE) + return EIO; + + mfs_sbload((void *)sbbuf, fs); + + if (fs->mfs_magic != SUPER_MAGIC) + return EINVAL; + if (fs->mfs_block_size < MINBSIZE) + return EINVAL; + if ((fs->mfs_block_size % 512) != 0) + return EINVAL; + if (SBSIZE > fs->mfs_block_size) + return EINVAL; + if ((fs->mfs_block_size % INODE_SIZE) != 0) + return EINVAL; + + /* For even larger disks, a similar problem occurs with s_firstdatazone. + * If the on-disk field contains zero, we assume that the value was too + * large to fit, and compute it on the fly. + */ + if (fs->mfs_firstdatazone_old == 0) { + block_t offset; + offset = START_BLOCK + fs->mfs_imap_blocks + fs->mfs_zmap_blocks; + offset += (fs->mfs_ninodes + fs->mfs_inodes_per_block - 1) / + fs->mfs_inodes_per_block; + + fs->mfs_firstdatazone = + (offset + (1 << fs->mfs_log_zone_size) - 1) >> + fs->mfs_log_zone_size; + } else { + fs->mfs_firstdatazone = (zone_t) fs->mfs_firstdatazone_old; + } + + if (fs->mfs_imap_blocks < 1 || fs->mfs_zmap_blocks < 1 + || fs->mfs_ninodes < 1 || fs->mfs_zones < 1 + || fs->mfs_firstdatazone <= 4 + || fs->mfs_firstdatazone >= fs->mfs_zones + || (unsigned) fs->mfs_log_zone_size > 4) + return EINVAL; + + /* compute in-memory mfs_sblock values */ + fs->mfs_inodes_per_block = fs->mfs_block_size / INODE_SIZE; + + + { + int32_t mult = fs->mfs_block_size >> LOG_MINBSIZE; + int ln2 = LOG_MINBSIZE; + + for (; mult != 1; ln2++) + mult >>= 1; + + fs->mfs_bshift = ln2; + /* XXX assume hw bsize = 512 */ + fs->mfs_fsbtodb = ln2 - LOG_MINBSIZE + 1; + } + + fs->mfs_qbmask = fs->mfs_block_size - 1; + fs->mfs_bmask = ~fs->mfs_qbmask; + + return 0; +} + +/* + * Open a file. + */ +__compactcall int +minixfs3_open(const char *path, struct open_file *f) +{ +#ifndef LIBSA_FS_SINGLECOMPONENT + const char *cp, *ncp; + int c; +#endif + ino32_t inumber; + struct file *fp; + struct mfs_sblock *fs; + int rc; +#ifndef LIBSA_NO_FS_SYMLINK + ino32_t parent_inumber; + int nlinks = 0; + char namebuf[MAXPATHLEN+1]; + char *buf; +#endif + + /* allocate file system specific data structure */ + fp = alloc(sizeof(struct file)); + memset(fp, 0, sizeof(struct file)); + f->f_fsdata = (void *)fp; + + /* allocate space and read super block */ + fs = alloc(sizeof(*fs)); + memset(fs, 0, sizeof(*fs)); + fp->f_fs = fs; + twiddle(); + + rc = read_sblock(f, fs); + if (rc) + goto out; + + /* alloc a block sized buffer used for all fs transfers */ + fp->f_buf = alloc(fs->mfs_block_size); + + /* + * Calculate indirect block levels. + */ + { + int32_t mult; + int ln2; + + /* + * We note that the number of indirect blocks is always + * a power of 2. This lets us use shifts and masks instead + * of divide and remainder and avoinds pulling in the + * 64bit division routine into the boot code. + */ + mult = NINDIR(fs); +#ifdef DEBUG + if (!powerof2(mult)) { + /* Hummm was't a power of 2 */ + rc = EINVAL; + goto out; + } +#endif + for (ln2 = 0; mult != 1; ln2++) + mult >>= 1; + + fp->f_nishift = ln2; + } + + inumber = ROOT_INODE; + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_FS_SINGLECOMPONENT + cp = path; + while (*cp) { + + /* + * Remove extra separators + */ + while (*cp == '/') + cp++; + if (*cp == '\0') + break; + + /* + * Check that current node is a directory. + */ + if ((fp->f_di.mdi_mode & I_TYPE) != I_DIRECTORY) { + rc = ENOTDIR; + goto out; + } + + /* + * Get next component of path name. + */ + ncp = cp; + while ((c = *cp) != '\0' && c != '/') + cp++; + + /* + * Look up component in current directory. + * Save directory inumber in case we find a + * symbolic link. + */ +#ifndef LIBSA_NO_FS_SYMLINK + parent_inumber = inumber; +#endif + rc = search_directory(ncp, cp - ncp, f, &inumber); + if (rc) + goto out; + + /* + * Open next component. + */ + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_NO_FS_SYMLINK + /* + * Check for symbolic link. + */ + if ((fp->f_di.mdi_mode & I_TYPE) == I_SYMBOLIC_LINK) { + int link_len = fp->f_di.mdi_size; + int len; + size_t buf_size; + block_t disk_block; + + len = strlen(cp); + + if (link_len + len > MAXPATHLEN || + ++nlinks > MAXSYMLINKS) { + rc = ENOENT; + goto out; + } + + memmove(&namebuf[link_len], cp, len + 1); + + /* + * Read file for symbolic link + */ + buf = fp->f_buf; + rc = block_map(f, (block_t)0, &disk_block); + if (rc) + goto out; + + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, + F_READ, FSBTODB(fs, disk_block), + fs->mfs_block_size, buf, &buf_size); + if (rc) + goto out; + + memcpy(namebuf, buf, link_len); + + /* + * If relative pathname, restart at parent directory. + * If absolute pathname, restart at root. + */ + cp = namebuf; + if (*cp != '/') + inumber = parent_inumber; + else + inumber = (ino32_t) ROOT_INODE; + + if ((rc = read_inode(inumber, f)) != 0) + goto out; + } +#endif /* !LIBSA_NO_FS_SYMLINK */ + } + + /* + * Found terminal component. + */ + rc = 0; + +#else /* !LIBSA_FS_SINGLECOMPONENT */ + + /* look up component in the current (root) directory */ + rc = search_directory(path, strlen(path), f, &inumber); + if (rc) + goto out; + + /* open it */ + rc = read_inode(inumber, f); + +#endif /* !LIBSA_FS_SINGLECOMPONENT */ + + fp->f_seekp = 0; /* reset seek pointer */ + +out: + if (rc) + minixfs3_close(f); + + return rc; +} + +__compactcall int +minixfs3_close(struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + + f->f_fsdata = NULL; + if (fp == NULL) + return 0; + + if (fp->f_buf) + dealloc(fp->f_buf, fp->f_fs->mfs_block_size); + dealloc(fp->f_fs, sizeof(*fp->f_fs)); + dealloc(fp, sizeof(struct file)); + return 0; +} + +/* + * Copy a portion of a file into kernel memory. + * Cross block boundaries when necessary. + */ +__compactcall int +minixfs3_read(struct open_file *f, void *start, size_t size, size_t *resid) +{ + struct file *fp = (struct file *)f->f_fsdata; + size_t csize; + char *buf; + size_t buf_size; + int rc = 0; + char *addr = start; + + while (size != 0) { + if (fp->f_seekp >= (off_t)fp->f_di.mdi_size) + break; + + rc = buf_read_file(f, &buf, &buf_size); + if (rc) + break; + + csize = size; + if (csize > buf_size) + csize = buf_size; + + memcpy(addr, buf, csize); + + fp->f_seekp += csize; + addr += csize; + size -= csize; + } + + if (resid) + *resid = size; + return rc; +} + +/* + * Not implemented. + */ +#ifndef LIBSA_NO_FS_WRITE +__compactcall int +minixfs3_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !LIBSA_NO_FS_WRITE */ + +#ifndef LIBSA_NO_FS_SEEK +__compactcall off_t +minixfs3_seek(struct open_file *f, off_t offset, int where) +{ + struct file *fp = (struct file *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + fp->f_seekp = offset; + break; + case SEEK_CUR: + fp->f_seekp += offset; + break; + case SEEK_END: + fp->f_seekp = fp->f_di.mdi_size - offset; + break; + default: + return -1; + } + return fp->f_seekp; +} +#endif /* !LIBSA_NO_FS_SEEK */ + +__compactcall int +minixfs3_stat(struct open_file *f, struct stat *sb) +{ + struct file *fp = (struct file *)f->f_fsdata; + + /* only important stuff */ + memset(sb, 0, sizeof *sb); + sb->st_mode = fp->f_di.mdi_mode; + sb->st_uid = fp->f_di.mdi_uid; + sb->st_gid = fp->f_di.mdi_gid; + sb->st_size = fp->f_di.mdi_size; + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +minixfs3_ls(struct open_file *f, const char *pattern) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct mfs_sblock *fs = fp->f_fs; + struct mfs_direct *dp; + struct mfs_direct *dbuf; + size_t buf_size; + entry_t *names = 0, *n, **np; + + fp->f_seekp = 0; + while (fp->f_seekp < (off_t)fp->f_di.mdi_size) { + int rc = buf_read_file(f, (char**)&dbuf, &buf_size); + if (rc) + goto out; + + /* XXX we assume, that buf_read_file reads an fs block and + * doesn't truncate buffer. Currently i_size in MFS doesn't + * the same as size of allocated blocks, it makes buf_read_file + * to truncate buf_size. + */ + if (buf_size < fs->mfs_block_size) + buf_size = fs->mfs_block_size; + + for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) { + char *cp; + int namlen; + + if (fs2h32(dp->mfsd_ino) == 0) + continue; + + if (pattern && !fn_match(dp->mfsd_name, pattern)) + continue; + + /* Compute the length of the name, + * We don't use strlen and strcpy, because original MFS + * code doesn't. + */ + cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name)); + if (cp == NULL) + namlen = sizeof(dp->mfsd_name); + else + namlen = cp - (dp->mfsd_name); + + n = alloc(sizeof *n + namlen); + if (!n) { + printf("%d: %s\n", + fs2h32(dp->mfsd_ino), dp->mfsd_name); + continue; + } + n->e_ino = fs2h32(dp->mfsd_ino); + strncpy(n->e_name, dp->mfsd_name, namlen); + n->e_name[namlen] = '\0'; + for (np = &names; *np; np = &(*np)->e_next) { + if (strcmp(n->e_name, (*np)->e_name) < 0) + break; + } + n->e_next = *np; + *np = n; + } + fp->f_seekp += buf_size; + } + + if (names) { + entry_t *p_names = names; + do { + n = p_names; + printf("%d: %s\n", + n->e_ino, n->e_name); + p_names = n->e_next; + } while (p_names); + } else { + printf("not found\n"); + } +out: + if (names) { + do { + n = names; + names = n->e_next; + dealloc(n, 0); + } while (names); + } + return; +} +#endif + +/* + * byte swap functions for big endian machines + * (mfs is always little endian) + */ + +/* These functions are only needed if native byte order is not big endian */ +#if BYTE_ORDER == BIG_ENDIAN +void +minixfs3_sb_bswap(struct mfs_sblock *old, struct mfs_sblock *new) +{ + new->mfs_ninodes = bswap32(old->mfs_ninodes); + new->mfs_nzones = bswap16(old->mfs_nzones); + new->mfs_imap_blocks = bswap16(old->mfs_imap_blocks); + new->mfs_zmap_blocks = bswap16(old->mfs_zmap_blocks); + new->mfs_firstdatazone_old = bswap16(old->mfs_firstdatazone_old); + new->mfs_log_zone_size = bswap16(old->mfs_log_zone_size); + new->mfs_max_size = bswap32(old->mfs_max_size); + new->mfs_zones = bswap32(old->mfs_zones); + new->mfs_magic = bswap16(old->mfs_magic); + new->mfs_block_size = bswap16(old->mfs_block_size); + new->mfs_disk_version = old->mfs_disk_version; +} + +void minixfs3_i_bswap(struct mfs_dinode *old, struct mfs_dinode *new) +{ + int i; + + new->mdi_mode = bswap16(old->mdi_mode); + new->mdi_nlinks = bswap16(old->mdi_nlinks); + new->mdi_uid = bswap16(old->mdi_uid); + new->mdi_gid = bswap16(old->mdi_gid); + new->mdi_size = bswap32(old->mdi_size); + new->mdi_atime = bswap32(old->mdi_atime); + new->mdi_mtime = bswap32(old->mdi_mtime); + new->mdi_ctime = bswap32(old->mdi_ctime); + + /* We don't swap here, because indirects must be swapped later + * anyway, hence everything is done by block_map(). + */ + for (i = 0; i < NR_TZONES; i++) + new->mdi_zone[i] = old->mdi_zone[i]; +} +#endif diff --git a/sys/lib/libsa/minixfs3.h b/sys/lib/libsa/minixfs3.h new file mode 100644 index 000000000..aef8a54f6 --- /dev/null +++ b/sys/lib/libsa/minixfs3.h @@ -0,0 +1,176 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2012 + * Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved. + * + * Author: Evgeniy Ivanov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MINIX_FS_3_H +#define MINIX_FS_3_H + +FS_DEF(minixfs3); + +typedef uint32_t zone_t; +typedef uint16_t zone1_t; +typedef uint32_t block_t; + +#define NR_DZONES 7 /* # direct zone numbers in an inode */ +#define NR_TZONES 10 /* total # zone numbers in an inode */ +#define NIADDR 2 /* Indirect addresses in inode */ + +struct mfs_dinode { + uint16_t mdi_mode; /* file type, protection, etc. */ + uint16_t mdi_nlinks; /* how many links to this file */ + int16_t mdi_uid; /* user id of the file's owner */ + uint16_t mdi_gid; /* group number */ + uint32_t mdi_size; /* current file size in bytes */ + uint32_t mdi_atime; /* time of last access */ + uint32_t mdi_mtime; /* when was file data last changed */ + uint32_t mdi_ctime; /* when was inode itself changed */ + zone_t mdi_zone[NR_TZONES]; /* zone numbers for direct, ind, and + dbl ind */ +}; + +/* Maximum Minix MFS on-disk directory filename. + * MFS uses 'struct direct' to write and parse + * directory entries, so this can't be changed + * without breaking filesystems. + */ +#define MFS_DIRSIZ 60 + +struct mfs_direct { + uint32_t mfsd_ino; + char mfsd_name[MFS_DIRSIZ]; +} __packed; + +struct mfs_sblock { + uint32_t mfs_ninodes; /* # usable inodes on the minor device */ + zone1_t mfs_nzones; /* total device size, including bit maps etc */ + int16_t mfs_imap_blocks; /* # of blocks used by inode bit map */ + int16_t mfs_zmap_blocks; /* # of blocks used by zone bit map */ + zone1_t mfs_firstdatazone_old;/* number of first data zone (small) */ + int16_t mfs_log_zone_size; /* log2 of blocks/zone */ + int16_t mfs_pad; /* try to avoid compiler-dependent padding */ + int32_t mfs_max_size; /* maximum file size on this device */ + zone_t mfs_zones; /* number of zones (replaces s_nzones in V2) */ + int16_t mfs_magic; /* magic number to recognize super-blocks */ + int16_t mfs_pad2; /* try to avoid compiler-dependent padding */ + uint16_t mfs_block_size; /* block size in bytes. */ + char mfs_disk_version; /* filesystem format sub-version */ + + /* The following items are only used when the super_block is in memory, + * mfs_inodes_per_block must be the firs one (see SBSIZE) + */ + unsigned mfs_inodes_per_block; /* precalculated from magic number */ + zone_t mfs_firstdatazone; /* number of first data zone (big) */ + int32_t mfs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t mfs_bmask; /* ``blkoff'' calc of blk offsets */ + int64_t mfs_qbmask; /* ~fs_bmask - for use with quad size */ + int32_t mfs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ +}; + +#define LOG_MINBSIZE 10 +#define MINBSIZE (1 << LOG_MINBSIZE) + +#define SUPER_MAGIC 0x4d5a /* magic # for MFSv3 file systems */ + +#define ROOT_INODE ((uint32_t) 1) /* inode number for root directory */ +#define SUPER_BLOCK_OFF (1024) /* bytes offset */ +#define START_BLOCK ((block_t) 2) /* first fs block (not counting SB) */ + +/* # bytes/dir entry */ +#define DIR_ENTRY_SIZE sizeof(struct mfs_direct) +/* # dir entries/blk */ +#define NR_DIR_ENTRIES(fs) ((fs)->mfs_block_size/DIR_ENTRY_SIZE) +/* mfs_sblock on-disk part size */ +#define SBSIZE offsetof(struct mfs_sblock, mfs_inodes_per_block) + +#define ZONE_NUM_SIZE sizeof(zone_t) /* # bytes in zone */ +#define INODE_SIZE sizeof(struct mfs_dinode) /* bytes in dsk ino */ +/* # zones/indir block */ +#define NINDIR(fs) ((fs)->mfs_block_size/ZONE_NUM_SIZE) + +#define NO_ZONE ((zone_t) 0) /* absence of a zone number */ +#define NO_BLOCK ((block_t) 0) /* absence of a block number */ + +/* Turn file system block numbers into disk block addresses */ +#define fsbtodb(fs, b) ((b) << (fs)->mfs_fsbtodb) + +#define ino_to_fsba(fs, x) \ + (((x) - 1) / (fs)->mfs_inodes_per_block + \ + START_BLOCK + (fs)->mfs_imap_blocks + (fs)->mfs_zmap_blocks) +#define ino_to_fsbo(fs, x) (((x) - 1) % (fs)->mfs_inodes_per_block) + +/* + * MFS metadatas are stored in little-endian byte order. These macros + * helps reading theses metadatas. + */ +#if BYTE_ORDER == LITTLE_ENDIAN +# define fs2h16(x) (x) +# define fs2h32(x) (x) +# define mfs_sbload(old, new) \ + memcpy((new), (old), SBSIZE); +# define mfs_iload(old, new) \ + memcpy((new),(old),sizeof(struct mfs_dinode)) +#else +void minixfs3_sb_bswap(struct mfs_sblock *, struct mfs_sblock *); +void minixfs3_i_bswap(struct mfs_dinode *, struct mfs_dinode *); +# define fs2h16(x) bswap16(x) +# define fs2h32(x) bswap32(x) +# define mfs_sbload(old, new) minixfs3_sb_bswap((old), (new)) +# define mfs_iload(old, new) minixfs3_i_bswap((old), (new)) +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->mfs_bsize) */ \ + ((loc) & (fs)->mfs_qbmask) +#define lblkno(fs, loc) /* calculates (loc / fs->mfs_bsize) */ \ + ((loc) >> (fs)->mfs_bshift) + +/* Flag bits for i_mode in the inode. */ +#define I_TYPE 0170000 /* this field gives inode type */ +#define I_UNIX_SOCKET 0140000 /* unix domain socket */ +#define I_SYMBOLIC_LINK 0120000 /* file is a symbolic link */ +#define I_REGULAR 0100000 /* regular file, not dir or special */ +#define I_BLOCK_SPECIAL 0060000 /* block special file */ +#define I_DIRECTORY 0040000 /* file is a directory */ +#define I_CHAR_SPECIAL 0020000 /* character special file */ +#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */ +#define I_SET_UID_BIT 0004000 /* set effective uid_t on exec */ +#define I_SET_GID_BIT 0002000 /* set effective gid_t on exec */ +#define I_SET_STCKY_BIT 0001000 /* sticky bit */ +#define ALL_MODES 0007777 /* all bits for user, group and others */ +#define RWX_MODES 0000777 /* mode bits for RWX only */ +#define R_BIT 0000004 /* Rwx protection bit */ +#define W_BIT 0000002 /* rWx protection bit */ +#define X_BIT 0000001 /* rwX protection bit */ +#define I_NOT_ALLOC 0000000 /* this inode is free */ + +#endif /* MINIX_FS_3_H */ diff --git a/sys/lib/libsa/net.c b/sys/lib/libsa/net.c new file mode 100644 index 000000000..8d037110a --- /dev/null +++ b/sys/lib/libsa/net.c @@ -0,0 +1,141 @@ +/* $NetBSD: net.c,v 1.35 2009/04/11 10:57:55 lukem Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include +#include +#include + +#ifdef _STANDALONE +#include "stand.h" +#define delay() +#else +#include +#include +#include +#define panic printf +#define delay() usleep(100000) +#define getsecs() time(NULL) +#endif + +#include "net.h" + +/* + * Send a packet and wait for a reply, with exponential backoff. + * + * The send routine must return the actual number of bytes written, + * or -1 on error. + * + * The receive routine can indicate success by returning the number of + * bytes read; it can return 0 to indicate EOF; it can return -1 with a + * non-zero errno to indicate failure; finally, it can return -1 with a + * zero errno to indicate it isn't done yet. + */ +ssize_t +sendrecv(struct iodesc *d, + ssize_t (*sproc)(struct iodesc *, void *, size_t), + void *sbuf, size_t ssize, + ssize_t (*rproc)(struct iodesc *, void *, size_t, saseconds_t), + void *rbuf, size_t rsize) +{ + ssize_t cc; + satime_t t, tlast; + saseconds_t tmo, tleft; + +#ifdef NET_DEBUG + if (debug) + printf("sendrecv: called\n"); +#endif + + tmo = MINTMO; + tlast = 0; + tleft = 0; + t = getsecs(); + for (;;) { + if (tleft <= 0) { + if (tmo >= MAXTMO) { + errno = ETIMEDOUT; + return -1; + } + cc = (*sproc)(d, sbuf, ssize); + + tleft = tmo; + tmo <<= 1; + if (tmo > MAXTMO) + tmo = MAXTMO; + + if (cc == -1) { + /* Error on transmit; wait before retrying */ + while ((getsecs() - t) < tmo) + delay(); + tleft = 0; + continue; + } + if ((size_t)cc < ssize) + panic("sendrecv: short write! (%zd < %zu)", + cc, ssize); + + tlast = t; + } + + /* Try to get a packet and process it. */ + cc = (*rproc)(d, rbuf, rsize, tleft); + /* Return on data, EOF or real error. */ + if (cc != -1 || errno != 0) + return cc; + + /* Timed out or didn't get the packet we're waiting for */ + t = getsecs(); + tleft -= t - tlast; + tlast = t; + } +} diff --git a/sys/lib/libsa/net.h b/sys/lib/libsa/net.h new file mode 100644 index 000000000..e163c8ca0 --- /dev/null +++ b/sys/lib/libsa/net.h @@ -0,0 +1,135 @@ +/* $NetBSD: net.h,v 1.26 2011/05/11 16:23:40 zoltan Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#ifndef _KERNEL /* XXX - see */ +#undef __IPADDR +#define __IPADDR(x) htonl((u_int32_t)(x)) +#endif + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } + +/* Returns true if n_long's on the same net */ +#define SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m)) + +#define MACPY(s, d) memcpy(d, s, 6) + +#define MAXTMO 20 /* seconds */ +#define MINTMO 2 /* seconds */ + +#define FNAME_SIZE 128 +#define IFNAME_SIZE 16 +#define RECV_SIZE 1536 /* XXX delete this */ + +/* + * How much room to leave for headers in UDP packets: + * 14: struct ether_header + * 20: struct ip + * 8: struct udphdr + * That's 42 but let's pad it out to 48 bytes. + */ +#define ETHERNET_HEADER_SIZE 14 +#define IP_HEADER_SIZE 20 +#define UDP_HEADER_SIZE 8 + +#define UDP_TOTAL_HEADER_SIZE (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE) + +/* + * How much room to leave for headers in TCP packets: + * 14: struct ether_header + * 20: struct ip + * 20: struct tcphdr + */ +#define TCP_HEADER_SIZE 20 + +#define TCP_TOTAL_HEADER_SIZE (ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE) + +extern u_char bcea[6]; +extern char rootpath[FNAME_SIZE]; +extern char bootfile[FNAME_SIZE]; +extern char hostname[FNAME_SIZE]; + +/* All of these are in network order. */ +extern struct in_addr myip; +extern struct in_addr rootip; +extern struct in_addr gateip; +extern n_long netmask; + +extern int debug; /* defined in the machdep sources */ + +/* ARP/RevARP functions: */ +u_char *arpwhohas(struct iodesc *, struct in_addr); +void arp_reply(struct iodesc *, void *); +int rarp_getipaddress(int); + +/* Link functions: */ +ssize_t sendether(struct iodesc *, void *, size_t, u_char *, int); +ssize_t readether(struct iodesc *, void *, size_t, saseconds_t, u_int16_t *); + +ssize_t sendip __P((struct iodesc *, void *, size_t, u_int8_t)); +ssize_t readip __P((struct iodesc *, void *, size_t, time_t, u_int8_t)); + +ssize_t sendudp(struct iodesc *, void *, size_t); +ssize_t readudp(struct iodesc *, void *, size_t, saseconds_t); + +int tcp_connect __P((struct iodesc *)); +ssize_t sendtcp __P((struct iodesc *, void *, size_t)); +ssize_t readtcp __P((struct iodesc *, void *, size_t, time_t)); + +ssize_t sendrecv(struct iodesc *, ssize_t (*)(struct iodesc *, void *, size_t), + void *, size_t, ssize_t (*)(struct iodesc *, void *, size_t, saseconds_t), + void *, size_t); + +/* Utilities: */ +char *ether_sprintf(const u_char *); +int ip_cksum(const void *, size_t); + +/* Machine-dependent functions: */ +#ifdef _STANDALONE /* XXX for mount_nfs(8) SMALLPROG hack */ +satime_t getsecs(void); +#endif diff --git a/sys/lib/libsa/netif.c b/sys/lib/libsa/netif.c new file mode 100644 index 000000000..ada313662 --- /dev/null +++ b/sys/lib/libsa/netif.c @@ -0,0 +1,322 @@ +/* $NetBSD: netif.c,v 1.24 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the Author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include "stand.h" +#include "netif.h" + +struct iodesc sockets[SOPEN_MAX]; +#ifdef NETIF_DEBUG +int netif_debug = 0; +#endif + +/* + * netif_init: + * + * initialize the generic network interface layer + */ + +void +netif_init(void) +{ + struct netif_driver *drv; + int d, i; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_init: called\n"); +#endif + for (d = 0; d < n_netif_drivers; d++) { + drv = netif_drivers[d]; + for (i = 0; i < drv->netif_nifs; i++) + drv->netif_ifs[i].dif_used = 0; + } +} + +int netif_match(struct netif *, void *); + +int +netif_match(struct netif *nif, void *machdep_hint) +{ + struct netif_driver *drv = nif->nif_driver; + +#if 0 + if (netif_debug) + printf("%s%d: netif_match (%d)\n", drv->netif_bname, + nif->nif_unit, nif->nif_sel); +#endif + return drv->netif_match(nif, machdep_hint); +} + +struct netif * +netif_select(void *machdep_hint) +{ + int d, u, unit_done, s; + struct netif_driver *drv; + struct netif cur_if; + static struct netif best_if; + int best_val; + int val; + + best_val = 0; + best_if.nif_driver = NULL; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_select: %d interfaces\n", n_netif_drivers); +#endif + + for (d = 0; d < n_netif_drivers; d++) { + cur_if.nif_driver = netif_drivers[d]; + drv = cur_if.nif_driver; + + for (u = 0; u < drv->netif_nifs; u++) { + cur_if.nif_unit = u; + unit_done = 0; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("\t%s%d:", drv->netif_bname, + cur_if.nif_unit); +#endif + + for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) { + cur_if.nif_sel = s; + + if (drv->netif_ifs[u].dif_used & (1 << s)) { +#ifdef NETIF_DEBUG + if (netif_debug) + printf(" [%d used]", s); +#endif + continue; + } + + val = netif_match(&cur_if, machdep_hint); +#ifdef NETIF_DEBUG + if (netif_debug) + printf(" [%d -> %d]", s, val); +#endif + if (val > best_val) { + best_val = val; + best_if = cur_if; + } + } +#ifdef NETIF_DEBUG + if (netif_debug) + printf("\n"); +#endif + } + } + + if (best_if.nif_driver == NULL) + return NULL; + + best_if.nif_driver-> + netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel); + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("netif_select: %s%d(%d) wins\n", + best_if.nif_driver->netif_bname, + best_if.nif_unit, best_if.nif_sel); +#endif + return &best_if; +} + +int +netif_probe(struct netif *nif, void *machdep_hint) +{ + struct netif_driver *drv = nif->nif_driver; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit); +#endif + return drv->netif_probe(nif, machdep_hint); +} + +void +netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint) +{ + struct netif_driver *drv = nif->nif_driver; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit); +#endif + desc->io_netif = nif; +#ifdef PARANOID + if (drv->netif_init == NULL) + panic("%s%d: no netif_init support", drv->netif_bname, + nif->nif_unit); +#endif + drv->netif_init(desc, machdep_hint); + (void)memset(drv->netif_ifs[nif->nif_unit].dif_stats, 0, + sizeof(struct netif_stats)); +} + +void +netif_detach(struct netif *nif) +{ + struct netif_driver *drv = nif->nif_driver; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit); +#endif +#ifdef PARANOID + if (drv->netif_end == NULL) + panic("%s%d: no netif_end support", drv->netif_bname, + nif->nif_unit); +#endif + drv->netif_end(nif); +} + +ssize_t +netif_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timo) +{ + struct netif *nif = desc->io_netif; + struct netif_driver *drv = nif->nif_driver; + ssize_t rv; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit); +#endif +#ifdef PARANOID + if (drv->netif_get == NULL) + panic("%s%d: no netif_get support", drv->netif_bname, + nif->nif_unit); +#endif + rv = drv->netif_get(desc, pkt, len, timo); +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_get returning %d\n", drv->netif_bname, + nif->nif_unit, (int)rv); +#endif + return rv; +} + +ssize_t +netif_put(struct iodesc *desc, void *pkt, size_t len) +{ + struct netif *nif = desc->io_netif; + struct netif_driver *drv = nif->nif_driver; + ssize_t rv; + +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit); +#endif +#ifdef PARANOID + if (drv->netif_put == NULL) + panic("%s%d: no netif_put support", drv->netif_bname, + nif->nif_unit); +#endif + rv = drv->netif_put(desc, pkt, len); +#ifdef NETIF_DEBUG + if (netif_debug) + printf("%s%d: netif_put returning %d\n", drv->netif_bname, + nif->nif_unit, (int)rv); +#endif + return rv; +} + +struct iodesc * +socktodesc(int sock) +{ +#if !defined(LIBSA_NO_FD_CHECKING) + if (sock >= SOPEN_MAX) { + errno = EBADF; + return NULL; + } +#endif + return &sockets[sock]; +} + +int +netif_open(void *machdep_hint) +{ + int fd; + struct iodesc *s; + struct netif *nif; + + /* find a free socket */ + for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++) + if (s->io_netif == (struct netif *)0) + goto fnd; + errno = EMFILE; + return -1; + +fnd: + (void)memset(s, 0, sizeof(*s)); + netif_init(); + nif = netif_select(machdep_hint); + if (!nif) + panic("netboot: no interfaces left untried"); + if (netif_probe(nif, machdep_hint)) { + printf("netboot: couldn't probe %s%d\n", + nif->nif_driver->netif_bname, nif->nif_unit); + errno = EINVAL; + return -1; + } + netif_attach(nif, s, machdep_hint); + + return fd; +} + +int +netif_close(int sock) +{ +#if !defined(LIBSA_NO_FD_CHECKING) + if (sock >= SOPEN_MAX) { + errno = EBADF; + return -1; + } +#endif + netif_detach(sockets[sock].io_netif); + sockets[sock].io_netif = (struct netif *)0; + + return 0; +} diff --git a/sys/lib/libsa/netif.h b/sys/lib/libsa/netif.h new file mode 100644 index 000000000..446f63ae2 --- /dev/null +++ b/sys/lib/libsa/netif.h @@ -0,0 +1,62 @@ +/* $NetBSD: netif.h,v 1.7 2009/01/17 14:00:36 tsutsui Exp $ */ + +#ifndef __SYS_LIBNETBOOT_NETIF_H +#define __SYS_LIBNETBOOT_NETIF_H + +#include "iodesc.h" + +struct netif; /* forward */ + +struct netif_driver { + char *netif_bname; + int (*netif_match)(struct netif *, void *); + int (*netif_probe)(struct netif *, void *); + void (*netif_init)(struct iodesc *, void *); + int (*netif_get)(struct iodesc *, void *, size_t, saseconds_t); + int (*netif_put)(struct iodesc *, void *, size_t); + void (*netif_end)(struct netif *); + struct netif_dif *netif_ifs; + int netif_nifs; +}; + +struct netif_dif { + int dif_unit; + int dif_nsel; + struct netif_stats *dif_stats; + void *dif_private; + /* the following fields are used internally by the netif layer */ + u_long dif_used; +}; + +struct netif_stats { + int collisions; + int collision_error; + int missed; + int sent; + int received; + int deferred; + int overflow; +}; + +struct netif { + struct netif_driver *nif_driver; + int nif_unit; + int nif_sel; + void *nif_devdata; +}; + +extern struct netif_driver *netif_drivers[]; /* machdep */ +extern int n_netif_drivers; + +extern int netif_debug; + +void netif_init(void); +struct netif *netif_select(void *); +int netif_probe(struct netif *, void *); +void netif_attach(struct netif *, struct iodesc *, void *); +void netif_detach(struct netif *); + +int netif_open(void *); +int netif_close(int); + +#endif /* __SYS_LIBNETBOOT_NETIF_H */ diff --git a/sys/lib/libsa/nfs.c b/sys/lib/libsa/nfs.c new file mode 100644 index 000000000..6fadec026 --- /dev/null +++ b/sys/lib/libsa/nfs.c @@ -0,0 +1,666 @@ +/* $NetBSD: nfs.c,v 1.47 2011/12/25 06:09:08 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * XXX Does not currently implement: + * XXX + * XXX LIBSA_NO_FS_CLOSE + * XXX LIBSA_NO_FS_SEEK + * XXX LIBSA_NO_FS_WRITE + * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?) + * XXX LIBSA_FS_SINGLECOMPONENT (does this even make sense?) + */ + +#include +#include +#include +#include +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include "rpcv2.h" +#include "nfsv2.h" + +#include "stand.h" +#include "net.h" +#include "nfs.h" +#include "rpc.h" + +/* Define our own NFS attributes */ +struct nfsv2_fattrs { + n_long fa_type; + n_long fa_mode; + n_long fa_nlink; + n_long fa_uid; + n_long fa_gid; + n_long fa_size; + n_long fa_blocksize; + n_long fa_rdev; + n_long fa_blocks; + n_long fa_fsid; + n_long fa_fileid; + struct nfsv2_time fa_atime; + struct nfsv2_time fa_mtime; + struct nfsv2_time fa_ctime; +}; + + +struct nfs_read_args { + u_char fh[NFS_FHSIZE]; + n_long off; + n_long len; + n_long xxx; /* XXX what's this for? */ +}; + +/* Data part of nfs rpc reply (also the largest thing we receive) */ +#define NFSREAD_SIZE 1024 +struct nfs_read_repl { + n_long errno; + struct nfsv2_fattrs fa; + n_long count; + u_char data[NFSREAD_SIZE]; +}; + +#ifndef NFS_NOSYMLINK +struct nfs_readlnk_repl { + n_long errno; + n_long len; + char path[NFS_MAXPATHLEN]; +}; +#endif + +struct nfs_iodesc { + struct iodesc *iodesc; + off_t off; + u_char fh[NFS_FHSIZE]; + struct nfsv2_fattrs fa; /* all in network order */ +}; + +struct nfs_iodesc nfs_root_node; + +int nfs_getrootfh(struct iodesc *, char *, u_char *); +int nfs_lookupfh(struct nfs_iodesc *, const char *, int, + struct nfs_iodesc *); +int nfs_readlink(struct nfs_iodesc *, char *); +ssize_t nfs_readdata(struct nfs_iodesc *, off_t, void *, size_t); + +/* + * Fetch the root file handle (call mount daemon) + * On error, return non-zero and set errno. + */ +int +nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp) +{ + int len; + struct args { + n_long len; + char path[FNAME_SIZE]; + } *args; + struct repl { + n_long errno; + u_char fh[NFS_FHSIZE]; + } *repl; + struct { + n_long h[RPC_HEADER_WORDS]; + struct args d; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct repl d; + } rdata; + ssize_t cc; + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_getrootfh: %s\n", path); +#endif + + args = &sdata.d; + repl = &rdata.d; + + (void)memset(args, 0, sizeof(*args)); + len = strlen(path); + if ((size_t)len > sizeof(args->path)) + len = sizeof(args->path); + args->len = htonl(len); + (void)memcpy(args->path, path, len); + len = 4 + roundup(len, 4); + + cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT, + args, len, repl, sizeof(*repl)); + if (cc == -1) { + /* errno was set by rpc_call */ + return -1; + } + if (cc < 4) { + errno = EBADRPC; + return -1; + } + if (repl->errno) { + errno = ntohl(repl->errno); + return -1; + } + (void)memcpy(fhp, repl->fh, sizeof(repl->fh)); + return 0; +} + +/* + * Lookup a file. Store handle and attributes. + * Return zero or error number. + */ +int +nfs_lookupfh(struct nfs_iodesc *d, const char *name, int len, + struct nfs_iodesc *newfd) +{ + int rlen; + struct args { + u_char fh[NFS_FHSIZE]; + n_long len; + char name[FNAME_SIZE]; + } *args; + struct repl { + n_long errno; + u_char fh[NFS_FHSIZE]; + struct nfsv2_fattrs fa; + } *repl; + struct { + n_long h[RPC_HEADER_WORDS]; + struct args d; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct repl d; + } rdata; + ssize_t cc; + +#ifdef NFS_DEBUG + if (debug) + printf("lookupfh: called\n"); +#endif + + args = &sdata.d; + repl = &rdata.d; + + (void)memset(args, 0, sizeof(*args)); + (void)memcpy(args->fh, d->fh, sizeof(args->fh)); + if ((size_t)len > sizeof(args->name)) + len = sizeof(args->name); + (void)memcpy(args->name, name, len); + args->len = htonl(len); + len = 4 + roundup(len, 4); + len += NFS_FHSIZE; + + rlen = sizeof(*repl); + + cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP, + args, len, repl, rlen); + if (cc == -1) + return errno; /* XXX - from rpc_call */ + if (cc < 4) + return EIO; + if (repl->errno) { + /* saerrno.h now matches NFS error numbers. */ + return ntohl(repl->errno); + } + (void)memcpy(&newfd->fh, repl->fh, sizeof(newfd->fh)); + (void)memcpy(&newfd->fa, &repl->fa, sizeof(newfd->fa)); + return 0; +} + +#ifndef NFS_NOSYMLINK +/* + * Get the destination of a symbolic link. + */ +int +nfs_readlink(struct nfs_iodesc *d, char *buf) +{ + struct { + n_long h[RPC_HEADER_WORDS]; + u_char fh[NFS_FHSIZE]; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct nfs_readlnk_repl d; + } rdata; + ssize_t cc; + +#ifdef NFS_DEBUG + if (debug) + printf("readlink: called\n"); +#endif + + (void)memcpy(sdata.fh, d->fh, NFS_FHSIZE); + cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK, + sdata.fh, NFS_FHSIZE, + &rdata.d, sizeof(rdata.d)); + if (cc == -1) + return errno; + + if (cc < 4) + return EIO; + + if (rdata.d.errno) + return ntohl(rdata.d.errno); + + rdata.d.len = ntohl(rdata.d.len); + if (rdata.d.len > NFS_MAXPATHLEN) + return ENAMETOOLONG; + + (void)memcpy(buf, rdata.d.path, rdata.d.len); + buf[rdata.d.len] = 0; + return 0; +} +#endif + +/* + * Read data from a file. + * Return transfer count or -1 (and set errno) + */ +ssize_t +nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len) +{ + struct nfs_read_args *args; + struct nfs_read_repl *repl; + struct { + n_long h[RPC_HEADER_WORDS]; + struct nfs_read_args d; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct nfs_read_repl d; + } rdata; + ssize_t cc; + long x; + size_t hlen, rlen; + + args = &sdata.d; + repl = &rdata.d; + + (void)memcpy(args->fh, d->fh, NFS_FHSIZE); + args->off = htonl((n_long)off); + if (len > NFSREAD_SIZE) + len = NFSREAD_SIZE; + args->len = htonl((n_long)len); + args->xxx = htonl((n_long)0); + hlen = sizeof(*repl) - NFSREAD_SIZE; + + cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ, + args, sizeof(*args), + repl, sizeof(*repl)); + if (cc == -1) { + /* errno was already set by rpc_call */ + return -1; + } + if (cc < (ssize_t)hlen) { + errno = EBADRPC; + return -1; + } + if (repl->errno) { + errno = ntohl(repl->errno); + return -1; + } + rlen = cc - hlen; + x = ntohl(repl->count); + if (rlen < (size_t)x) { + printf("nfsread: short packet, %lu < %ld\n", (u_long) rlen, x); + errno = EBADRPC; + return -1; + } + (void)memcpy(addr, repl->data, x); + return x; +} + +/* + * nfs_mount - mount this nfs filesystem to a host + * On error, return non-zero and set errno. + */ +int +nfs_mount(int sock, struct in_addr ip, char *path) +{ + struct iodesc *desc; + struct nfsv2_fattrs *fa; + + if (!(desc = socktodesc(sock))) { + errno = EINVAL; + return -1; + } + + /* Bind to a reserved port. */ + desc->myport = htons(--rpc_port); + desc->destip = ip; + if (nfs_getrootfh(desc, path, nfs_root_node.fh)) + return -1; + nfs_root_node.iodesc = desc; + /* Fake up attributes for the root dir. */ + fa = &nfs_root_node.fa; + fa->fa_type = htonl(NFDIR); + fa->fa_mode = htonl(0755); + fa->fa_nlink = htonl(2); + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_mount: got fh for %s\n", path); +#endif + + return 0; +} + +/* + * Open a file. + * return zero or error number + */ +__compactcall int +nfs_open(const char *path, struct open_file *f) +{ + struct nfs_iodesc *newfd, *currfd; + const char *cp; +#ifndef NFS_NOSYMLINK + const char *ncp; + int c; + char namebuf[NFS_MAXPATHLEN + 1]; + char linkbuf[NFS_MAXPATHLEN + 1]; + int nlinks = 0; +#endif + int error = 0; + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_open: %s\n", path); +#endif + if (nfs_root_node.iodesc == NULL) { + printf("nfs_open: must mount first.\n"); + return ENXIO; + } + + currfd = &nfs_root_node; + newfd = 0; + +#ifndef NFS_NOSYMLINK + cp = path; + while (*cp) { + /* + * Remove extra separators + */ + while (*cp == '/') + cp++; + + if (*cp == '\0') + break; + /* + * Check that current node is a directory. + */ + if (currfd->fa.fa_type != htonl(NFDIR)) { + error = ENOTDIR; + goto out; + } + + /* allocate file system specific data structure */ + newfd = alloc(sizeof(*newfd)); + newfd->iodesc = currfd->iodesc; + newfd->off = 0; + + /* + * Get next component of path name. + */ + { + int len = 0; + + ncp = cp; + while ((c = *cp) != '\0' && c != '/') { + if (++len > NFS_MAXNAMLEN) { + error = ENOENT; + goto out; + } + cp++; + } + } + + /* lookup a file handle */ + error = nfs_lookupfh(currfd, ncp, cp - ncp, newfd); + if (error) + goto out; + + /* + * Check for symbolic link + */ + if (newfd->fa.fa_type == htonl(NFLNK)) { + int link_len, len; + + error = nfs_readlink(newfd, linkbuf); + if (error) + goto out; + + link_len = strlen(linkbuf); + len = strlen(cp); + + if (link_len + len > MAXPATHLEN + || ++nlinks > MAXSYMLINKS) { + error = ENOENT; + goto out; + } + + (void)memcpy(&namebuf[link_len], cp, len + 1); + (void)memcpy(namebuf, linkbuf, link_len); + + /* + * If absolute pathname, restart at root. + * If relative pathname, restart at parent directory. + */ + cp = namebuf; + if (*cp == '/') { + if (currfd != &nfs_root_node) + dealloc(currfd, sizeof(*currfd)); + currfd = &nfs_root_node; + } + + dealloc(newfd, sizeof(*newfd)); + newfd = 0; + + continue; + } + + if (currfd != &nfs_root_node) + dealloc(currfd, sizeof(*currfd)); + currfd = newfd; + newfd = 0; + } + + error = 0; + +out: +#else + /* allocate file system specific data structure */ + currfd = alloc(sizeof(*currfd)); + currfd->iodesc = nfs_root_node.iodesc; + currfd->off = 0; + + cp = path; + /* + * Remove extra separators + */ + while (*cp == '/') + cp++; + + /* XXX: Check for empty path here? */ + + error = nfs_lookupfh(&nfs_root_node, cp, strlen(cp), currfd); +#endif + if (!error) { + f->f_fsdata = (void *)currfd; + fsmod = "nfs"; + return 0; + } + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_open: %s lookupfh failed: %s\n", + path, strerror(error)); +#endif + if (currfd != &nfs_root_node) + dealloc(currfd, sizeof(*currfd)); + if (newfd) + dealloc(newfd, sizeof(*newfd)); + + return error; +} + +__compactcall int +nfs_close(struct open_file *f) +{ + struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_close: fp=0x%lx\n", (u_long)fp); +#endif + + if (fp) + dealloc(fp, sizeof(struct nfs_iodesc)); + f->f_fsdata = (void *)0; + + return 0; +} + +/* + * read a portion of a file + */ +__compactcall int +nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; + ssize_t cc; + char *addr = buf; + +#ifdef NFS_DEBUG + if (debug) + printf("nfs_read: size=%lu off=%d\n", (u_long)size, + (int)fp->off); +#endif + while ((int)size > 0) { +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + cc = nfs_readdata(fp, fp->off, (void *)addr, size); + /* XXX maybe should retry on certain errors */ + if (cc == -1) { +#ifdef NFS_DEBUG + if (debug) + printf("nfs_read: read: %s\n", + strerror(errno)); +#endif + return errno; /* XXX - from nfs_readdata */ + } + if (cc == 0) { +#ifdef NFS_DEBUG + if (debug) + printf("nfs_read: hit EOF unexpectantly\n"); +#endif + goto ret; + } + fp->off += cc; + addr += cc; + size -= cc; + } +ret: + if (resid) + *resid = size; + + return 0; +} + +/* + * Not implemented. + */ +__compactcall int +nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + return EROFS; +} + +__compactcall off_t +nfs_seek(struct open_file *f, off_t offset, int where) +{ + struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata; + n_long size = ntohl(d->fa.fa_size); + + switch (where) { + case SEEK_SET: + d->off = offset; + break; + case SEEK_CUR: + d->off += offset; + break; + case SEEK_END: + d->off = size - offset; + break; + default: + return -1; + } + + return d->off; +} + +/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */ +const int nfs_stat_types[8] = { + 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 }; + +__compactcall int +nfs_stat(struct open_file *f, struct stat *sb) +{ + struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata; + n_long ftype, mode; + + ftype = ntohl(fp->fa.fa_type); + mode = ntohl(fp->fa.fa_mode); + mode |= nfs_stat_types[ftype & 7]; + + sb->st_mode = mode; + sb->st_nlink = ntohl(fp->fa.fa_nlink); + sb->st_uid = ntohl(fp->fa.fa_uid); + sb->st_gid = ntohl(fp->fa.fa_gid); + sb->st_size = ntohl(fp->fa.fa_size); + + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +nfs_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by nfs\n"); + return; +} +#endif diff --git a/sys/lib/libsa/nfs.h b/sys/lib/libsa/nfs.h new file mode 100644 index 000000000..937812602 --- /dev/null +++ b/sys/lib/libsa/nfs.h @@ -0,0 +1,33 @@ +/* $NetBSD: nfs.h,v 1.8 2005/12/11 12:24:46 christos Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +FS_DEF(nfs); +int nfs_mount(int, struct in_addr, char *); diff --git a/sys/lib/libsa/nfsv2.h b/sys/lib/libsa/nfsv2.h new file mode 100644 index 000000000..c8402a152 --- /dev/null +++ b/sys/lib/libsa/nfsv2.h @@ -0,0 +1,162 @@ +/* $NetBSD: nfsv2.h,v 1.4 2005/12/11 12:24:46 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsv2.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * nfs definitions as per the version 2 specs + */ + +/* + * Constants as defined in the Sun NFS Version 2 spec. + * "NFS: Network File System Protocol Specification" RFC1094 + */ + +#define NFS_PORT 2049 +#define NFS_PROG 100003 +#define NFS_VER2 2 +#define NFS_MAXDGRAMDATA 8192 +#define NFS_MAXDATA 32768 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_FHSIZE 32 +#define NFS_MAXPKTHDR 404 +#define NFS_MAXPACKET (NFS_MAXPKTHDR+NFS_MAXDATA) +#define NFS_MINPACKET 20 +#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ + +/* Stat numbers for rpc returns */ +#define NFS_OK 0 +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_IO 5 +#define NFSERR_NXIO 6 +#define NFSERR_ACCES 13 +#define NFSERR_EXIST 17 +#define NFSERR_NODEV 19 +#define NFSERR_NOTDIR 20 +#define NFSERR_ISDIR 21 +#define NFSERR_FBIG 27 +#define NFSERR_NOSPC 28 +#define NFSERR_ROFS 30 +#define NFSERR_NAMETOL 63 +#define NFSERR_NOTEMPTY 66 +#define NFSERR_DQUOT 69 +#define NFSERR_STALE 70 +#define NFSERR_WFLUSH 99 + +/* Sizes in bytes of various nfs rpc components */ +#define NFSX_FH 32 +#define NFSX_UNSIGNED 4 +#define NFSX_FATTR 68 +#define NFSX_SATTR 32 +#define NFSX_STATFS 20 +#define NFSX_COOKIE 4 + +/* nfs rpc procedure numbers */ +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_NOOP 3 +#define NFSPROC_ROOT NFSPROC_NOOP /* Obsolete */ +#define NFSPROC_LOOKUP 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITECACHE NFSPROC_NOOP /* Obsolete */ +#define NFSPROC_WRITE 8 +#define NFSPROC_CREATE 9 +#define NFSPROC_REMOVE 10 +#define NFSPROC_RENAME 11 +#define NFSPROC_LINK 12 +#define NFSPROC_SYMLINK 13 +#define NFSPROC_MKDIR 14 +#define NFSPROC_RMDIR 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_STATFS 17 + +#define NFS_NPROCS 18 + + +/* File types */ +typedef enum { + NFNON=0, + NFREG=1, + NFDIR=2, + NFBLK=3, + NFCHR=4, + NFLNK=5 +} nfstype; + +/* Structs for common parts of the rpc's */ +struct nfsv2_time { + n_long nfs_sec; + n_long nfs_usec; +}; + +/* + * File attributes and setable attributes. + */ +struct nfsv2_fattr { + n_long fa_type; + n_long fa_mode; + n_long fa_nlink; + n_long fa_uid; + n_long fa_gid; + n_long fa_size; + n_long fa_blocksize; + n_long fa_rdev; + n_long fa_blocks; + n_long fa_fsid; + n_long fa_fileid; + struct nfsv2_time fa_atime; + struct nfsv2_time fa_mtime; + struct nfsv2_time fa_ctime; +}; + +struct nfsv2_sattr { + n_long sa_mode; + n_long sa_uid; + n_long sa_gid; + n_long sa_size; + struct nfsv2_time sa_atime; + struct nfsv2_time sa_mtime; +}; + +struct nfsv2_statfs { + n_long sf_tsize; + n_long sf_bsize; + n_long sf_blocks; + n_long sf_bfree; + n_long sf_bavail; +}; diff --git a/sys/lib/libsa/nullfs.c b/sys/lib/libsa/nullfs.c new file mode 100644 index 000000000..558de6011 --- /dev/null +++ b/sys/lib/libsa/nullfs.c @@ -0,0 +1,124 @@ +/* $NetBSD: nullfs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)open.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +/* + * Null filesystem + */ + +__compactcall int +null_open(const char *path, struct open_file *f) +{ + + return EIO; +} + +#ifndef LIBSA_NO_FS_CLOSE +__compactcall int +null_close(struct open_file *f) +{ + + return 0; +} +#endif + +__compactcall int +null_read(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + + return EIO; +} + +#ifndef LIBSA_NO_FS_WRITE +__compactcall int +null_write(struct open_file *f, void *buf, size_t size, size_t *resid) +{ + + return EIO; +} +#endif + +#ifndef LIBSA_NO_FS_SEEK +__compactcall off_t +null_seek(struct open_file *f, off_t offset, int where) +{ + + return (off_t)-1; +} +#endif + +__compactcall int +null_stat(struct open_file *f, struct stat *sb) +{ + + return EIO; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +null_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by nullfs\n"); + return; +} +#endif diff --git a/sys/lib/libsa/open.c b/sys/lib/libsa/open.c new file mode 100644 index 000000000..c29c95aae --- /dev/null +++ b/sys/lib/libsa/open.c @@ -0,0 +1,157 @@ +/* $NetBSD: open.c,v 1.26 2007/11/24 13:20:56 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)open.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include "stand.h" + +/* + * File primitives proper + */ + +#ifdef HELLO_CTAGS +oopen(){} +#endif + +int +#ifndef __INTERNAL_LIBSA_CREAD +open(const char *fname, int mode) +#else +oopen(const char *fname, int mode) +#endif +{ + struct open_file *f; + int fd, error; +#if !defined(LIBSA_SINGLE_FILESYSTEM) + int i, besterror; +#endif + char *file; + + /* find a free file descriptor */ + for (fd = 0, f = files; fd < SOPEN_MAX; fd++, f++) + if (f->f_flags == 0) + goto fnd; + errno = EMFILE; + return -1; +fnd: + /* + * Try to open the device. + * Convert open mode (0,1,2) to F_READ, F_WRITE. + */ + f->f_flags = mode + 1; +#if !defined(LIBSA_SINGLE_DEVICE) + f->f_dev = (struct devsw *)0; +#endif +#if !defined(LIBSA_SINGLE_FILESYSTEM) + f->f_ops = (struct fs_ops *)0; +#endif +#if !defined(LIBSA_NO_RAW_ACCESS) + f->f_offset = 0; +#endif + file = (char *)0; + error = devopen(f, fname, &file); + if (error +#if !defined(LIBSA_SINGLE_DEVICE) + || (((f->f_flags & F_NODEV) == 0) && + f->f_dev == (struct devsw *)0) +#endif + ) + goto err; + +#if !defined(LIBSA_NO_RAW_ACCESS) + /* see if we opened a raw device; otherwise, 'file' is the file name. */ + if (file == (char *)0 || *file == '\0') { + f->f_flags |= F_RAW; + return fd; + } +#endif + + /* pass file name to the different filesystem open routines */ +#if !defined(LIBSA_SINGLE_FILESYSTEM) + besterror = ENOENT; + for (i = 0; i < nfsys; i++) { + error = FS_OPEN(&file_system[i])(file, f); + if (error == 0) { + f->f_ops = &file_system[i]; + return fd; + } + if (error != EINVAL) + besterror = error; + } + error = besterror; +#else + error = FS_OPEN(&file_system[i])(file, f); + if (error == 0) + return fd; + if (error == EINVAL) + error = ENOENT; +#endif + + if ((f->f_flags & F_NODEV) == 0) { +#if !defined(LIBSA_SINGLE_DEVICE) + if (DEV_CLOSE(f->f_dev) != NULL) +#endif + (void)DEV_CLOSE(f->f_dev)(f); + } +err: + f->f_flags = 0; + errno = error; + return -1; +} diff --git a/sys/lib/libsa/panic.c b/sys/lib/libsa/panic.c new file mode 100644 index 000000000..c91adfcc0 --- /dev/null +++ b/sys/lib/libsa/panic.c @@ -0,0 +1,53 @@ +/* $NetBSD: panic.c,v 1.7 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include + +#include "stand.h" + +__dead void +panic(const char *fmt, ...) +{ + va_list ap; +#ifndef LIBSA_NO_FS_CLOSE + static int paniced; + + if (!paniced) { + paniced = 1; + closeall(); + } +#endif + + va_start(ap, fmt); + vprintf(fmt, ap); + printf("\n"); + va_end(ap); + _rtt(); + /*NOTREACHED*/ +} diff --git a/sys/lib/libsa/printf.c b/sys/lib/libsa/printf.c new file mode 100644 index 000000000..ba3dc4f51 --- /dev/null +++ b/sys/lib/libsa/printf.c @@ -0,0 +1,48 @@ +/* $NetBSD: printf.c,v 1.18 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include +#include + +#include "stand.h" + +void +printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} diff --git a/sys/lib/libsa/qsort.c b/sys/lib/libsa/qsort.c new file mode 100644 index 000000000..206be0b65 --- /dev/null +++ b/sys/lib/libsa/qsort.c @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/libkern/qsort.c,v 1.12 2002/11/09 12:55:06 alfred Exp $ + * $NetBSD: qsort.c,v 1.4 2007/11/24 13:20:56 isaki Exp $ + */ + +#include +#include + +typedef int cmp_t(const void *, const void *); +static inline char *med3(char *, char *, char *, cmp_t *); +static inline void swapfunc(char *, char *, int, int); + +#define min(a, b) (a) < (b) ? (a) : (b) + +void qsort(void *a, size_t n, size_t es, cmp_t *cmp); + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *)(parmi); \ + register TYPE *pj = (TYPE *)(parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc(char *a, char *b, int n, int swaptype) +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +static inline char * +med3(char *a, char *b, char *c, cmp_t *cmp) +{ + return cmp(a, b) < 0 ? + (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) + :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +} + +void +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: + SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp); + pm = med3(pm - d, pm, pm + d, cmp); + pn = med3(pn - 2 * d, pn - d, pn, cmp); + } + pm = med3(pl, pm, pn, cmp); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (r = cmp(pb, a)) <= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = cmp(pc, a)) >= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; pl > (char *)a && cmp(pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + qsort(a, r / es, es, cmp); + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} diff --git a/sys/lib/libsa/rarp.c b/sys/lib/libsa/rarp.c new file mode 100644 index 000000000..1e0a717b7 --- /dev/null +++ b/sys/lib/libsa/rarp.c @@ -0,0 +1,240 @@ +/* $NetBSD: rarp.c,v 1.31 2011/05/11 16:23:40 zoltan Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL) + */ +#include +#include +#include +#include +#include + +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#include "net.h" + + +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +static ssize_t rarpsend(struct iodesc *, void *, size_t); +static ssize_t rarprecv(struct iodesc *, void *, size_t, saseconds_t); + +/* + * Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826). + */ +int +rarp_getipaddress(int sock) +{ + struct iodesc *d; + struct ether_arp *ap; + struct { + u_char header[ETHERNET_HEADER_SIZE]; + struct { + struct ether_arp arp; + u_char pad[18]; /* 60 - sizeof(arp) */ + } data; + } wbuf; + struct { + u_char header[ETHERNET_HEADER_SIZE]; + struct { + struct ether_arp arp; + u_char pad[24]; /* extra space */ + } data; + } rbuf; + +#ifdef RARP_DEBUG + if (debug) + printf("rarp: socket=%d\n", sock); +#endif + if (!(d = socktodesc(sock))) { + printf("rarp: bad socket. %d\n", sock); + return -1; + } +#ifdef RARP_DEBUG + if (debug) + printf("rarp: d=%lx\n", (u_long)d); +#endif + + (void)memset(&wbuf.data, 0, sizeof(wbuf.data)); + ap = &wbuf.data.arp; + ap->arp_hrd = htons(ARPHRD_ETHER); + ap->arp_pro = htons(ETHERTYPE_IP); + ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */ + ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */ + ap->arp_op = htons(ARPOP_REVREQUEST); + (void)memcpy(ap->arp_sha, d->myea, 6); + (void)memcpy(ap->arp_tha, d->myea, 6); + + if (sendrecv(d, + rarpsend, &wbuf.data, sizeof(wbuf.data), + rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0) + { + printf("No response for RARP request\n"); + return -1; + } + + ap = &rbuf.data.arp; + (void)memcpy(&myip, ap->arp_tpa, sizeof(myip)); +#if 0 + /* XXX - Can NOT assume this is our root server! */ + (void)memcpy(&rootip, ap->arp_spa, sizeof(rootip)); +#endif + + /* Compute our "natural" netmask. */ + if (IN_CLASSA(myip.s_addr)) + netmask = IN_CLASSA_NET; + else if (IN_CLASSB(myip.s_addr)) + netmask = IN_CLASSB_NET; + else + netmask = IN_CLASSC_NET; + + d->myip = myip; + return 0; +} + +/* + * Broadcast a RARP request (i.e. who knows who I am) + */ +static ssize_t +rarpsend(struct iodesc *d, void *pkt, size_t len) +{ + +#ifdef RARP_DEBUG + if (debug) + printf("rarpsend: called\n"); +#endif + + return sendether(d, pkt, len, bcea, ETHERTYPE_REVARP); +} + +/* + * Returns 0 if this is the packet we're waiting for + * else -1 (and errno == 0) + */ +static ssize_t +rarprecv(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + ssize_t n; + struct ether_arp *ap; + u_int16_t etype; /* host order */ + +#ifdef RARP_DEBUG + if (debug) + printf("rarprecv: "); +#endif + + n = readether(d, pkt, len, tleft, &etype); + errno = 0; /* XXX */ + if (n == -1 || (size_t)n < sizeof(struct ether_arp)) { +#ifdef RARP_DEBUG + if (debug) + printf("bad len=%d\n", (int)n); +#endif + return -1; + } + + if (etype != ETHERTYPE_REVARP) { +#ifdef RARP_DEBUG + if (debug) + printf("bad type=0x%x\n", etype); +#endif + return -1; + } + + ap = (struct ether_arp *)pkt; + if (ap->arp_hrd != htons(ARPHRD_ETHER) || + ap->arp_pro != htons(ETHERTYPE_IP) || + ap->arp_hln != sizeof(ap->arp_sha) || + ap->arp_pln != sizeof(ap->arp_spa) ) + { +#ifdef RARP_DEBUG + if (debug) + printf("bad hrd/pro/hln/pln\n"); +#endif + return -1; + } + + if (ap->arp_op != htons(ARPOP_REVREPLY)) { +#ifdef RARP_DEBUG + if (debug) + printf("bad op=0x%x\n", ntohs(ap->arp_op)); +#endif + return -1; + } + + /* Is the reply for our Ethernet address? */ + if (memcmp(ap->arp_tha, d->myea, 6)) { +#ifdef RARP_DEBUG + if (debug) + printf("unwanted address\n"); +#endif + return -1; + } + + /* We have our answer. */ +#ifdef RARP_DEBUG + if (debug) + printf("got it\n"); +#endif + return n; +} diff --git a/sys/lib/libsa/read.c b/sys/lib/libsa/read.c new file mode 100644 index 000000000..1e4752cea --- /dev/null +++ b/sys/lib/libsa/read.c @@ -0,0 +1,99 @@ +/* $NetBSD: read.c,v 1.15 2007/12/02 04:59:26 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)read.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include "stand.h" + +ssize_t +#ifndef __INTERNAL_LIBSA_CREAD +read(int fd, void *dest, size_t bcount) +#else +oread(int fd, void *dest, size_t bcount) +#endif +{ + struct open_file *f = &files[fd]; + size_t resid; + +#if !defined(LIBSA_NO_FD_CHECKING) + if ((unsigned int)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) { + errno = EBADF; + return -1; + } +#endif +#if !defined(LIBSA_NO_RAW_ACCESS) + if (f->f_flags & F_RAW) { +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + errno = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + btodb(f->f_offset), bcount, dest, &resid); + if (errno) + return -1; + f->f_offset += resid; + return resid; + } +#endif + resid = bcount; + if ((errno = FS_READ(f->f_ops)(f, dest, bcount, &resid))) + return -1; + return (ssize_t)(bcount - resid); +} diff --git a/sys/lib/libsa/rpc.c b/sys/lib/libsa/rpc.c new file mode 100644 index 000000000..b0ec1689c --- /dev/null +++ b/sys/lib/libsa/rpc.c @@ -0,0 +1,441 @@ +/* $NetBSD: rpc.c,v 1.29 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) + */ + +/* + * RPC functions used by NFS and bootparams. + * Note that bootparams requires the ability to find out the + * address of the server from which its response has come. + * This is supported by keeping the IP/UDP headers in the + * buffer space provided by the caller. (See rpc_fromaddr) + */ + +#include +#include + +#include +#include + +#ifdef _STANDALONE +#include +#include "stand.h" +#else +#include +#include +#include +#endif + +#include "rpcv2.h" + +#include "net.h" +#include "rpc.h" + +struct auth_info { + int32_t authtype; /* auth type */ + u_int32_t authlen; /* auth length */ +}; + +struct auth_unix { + int32_t ua_time; + int32_t ua_hostname; /* null */ + int32_t ua_uid; + int32_t ua_gid; + int32_t ua_gidlist; /* null */ +}; + +struct rpc_call { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (0) */ + u_int32_t rp_rpcvers; /* rpc version (2) */ + u_int32_t rp_prog; /* program */ + u_int32_t rp_vers; /* version */ + u_int32_t rp_proc; /* procedure */ +}; + +struct rpc_reply { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (1) */ + int32_t rp_astatus; /* accept status (0: accepted) */ + union { + u_int32_t rpu_errno; + struct { + struct auth_info rok_auth; + u_int32_t rok_status; + } rpu_rok; + } rp_u; +}; + +/* Local forwards */ +static ssize_t recvrpc(struct iodesc *, void *, size_t, saseconds_t); + +int rpc_xid; +int rpc_port = 0x400; /* predecrement */ + +/* + * Make a rpc call; return length of answer + * Note: Caller must leave room for headers. + */ +ssize_t +rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, + void *sdata, size_t slen, void *rdata, size_t rlen) +{ + ssize_t cc; + struct auth_info *auth; + struct rpc_call *call; + struct rpc_reply *reply; + char *send_head, *send_tail; + char *recv_head, *recv_tail; + n_long x; + int port; /* host order */ + +#ifdef RPC_DEBUG + if (debug) + printf("rpc_call: prog=0x%x vers=%d proc=%d\n", + prog, vers, proc); +#endif + + port = rpc_getport(d, prog, vers); + if (port == -1) + return -1; + + d->destport = htons(port); + + /* + * Prepend authorization stuff and headers. + * Note, must prepend things in reverse order. + */ + send_head = sdata; + send_tail = (char *)sdata + slen; + + /* Auth verifier is always auth_null */ + send_head -= sizeof(*auth); + auth = (struct auth_info *)send_head; + auth->authtype = htonl(RPCAUTH_NULL); + auth->authlen = 0; + +#if 1 + /* Auth credentials: always auth unix (as root) */ + send_head -= sizeof(struct auth_unix); + (void)memset(send_head, 0, sizeof(struct auth_unix)); + send_head -= sizeof(*auth); + auth = (struct auth_info *)send_head; + auth->authtype = htonl(RPCAUTH_UNIX); + auth->authlen = htonl(sizeof(struct auth_unix)); +#else + /* Auth credentials: always auth_null (XXX OK?) */ + send_head -= sizeof(*auth); + auth = send_head; + auth->authtype = htonl(RPCAUTH_NULL); + auth->authlen = 0; +#endif + + /* RPC call structure. */ + send_head -= sizeof(*call); + call = (struct rpc_call *)send_head; + rpc_xid++; + call->rp_xid = htonl(rpc_xid); + call->rp_direction = htonl(RPC_CALL); + call->rp_rpcvers = htonl(RPC_VER2); + call->rp_prog = htonl(prog); + call->rp_vers = htonl(vers); + call->rp_proc = htonl(proc); + + /* Make room for the rpc_reply header. */ + recv_head = rdata; + recv_tail = (char *)rdata + rlen; + recv_head -= sizeof(*reply); + + cc = sendrecv(d, + sendudp, send_head, send_tail - send_head, + recvrpc, recv_head, recv_tail - recv_head); + +#ifdef RPC_DEBUG + if (debug) + printf("callrpc: cc=%ld rlen=%lu\n", (long)cc, (u_long)rlen); +#endif + if (cc == -1) + return -1; + + if ((size_t)cc <= sizeof(*reply)) { + errno = EBADRPC; + return -1; + } + + recv_tail = recv_head + cc; + + /* + * Check the RPC reply status. + * The xid, dir, astatus were already checked. + */ + reply = (struct rpc_reply *)recv_head; + auth = &reply->rp_u.rpu_rok.rok_auth; + x = ntohl(auth->authlen); + if (x != 0) { +#ifdef RPC_DEBUG + if (debug) + printf("callrpc: reply auth != NULL\n"); +#endif + errno = EBADRPC; + return -1; + } + x = ntohl(reply->rp_u.rpu_rok.rok_status); + if (x != 0) { + printf("callrpc: error = %d\n", x); + errno = EBADRPC; + return -1; + } + recv_head += sizeof(*reply); + + return (ssize_t)(recv_tail - recv_head); +} + +/* + * Returns true if packet is the one we're waiting for. + * This just checks the XID, direction, acceptance. + * Remaining checks are done by callrpc + */ +static ssize_t +recvrpc(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + struct rpc_reply *reply; + ssize_t n; + int x; + + errno = 0; +#ifdef RPC_DEBUG + if (debug) + printf("recvrpc: called len=%lu\n", (u_long)len); +#endif + + n = readudp(d, pkt, len, tleft); + if (n <= (4 * 4)) + return -1; + + reply = (struct rpc_reply *)pkt; + + x = ntohl(reply->rp_xid); + if (x != rpc_xid) { +#ifdef RPC_DEBUG + if (debug) + printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid); +#endif + return -1; + } + + x = ntohl(reply->rp_direction); + if (x != RPC_REPLY) { +#ifdef RPC_DEBUG + if (debug) + printf("recvrpc: rp_direction %d != REPLY\n", x); +#endif + return -1; + } + + x = ntohl(reply->rp_astatus); + if (x != RPC_MSGACCEPTED) { + errno = ntohl(reply->rp_u.rpu_errno); + printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno); + return -1; + } + + /* Return data count (thus indicating success) */ + return n; +} + +/* + * Given a pointer to a reply just received, + * dig out the IP address/port from the headers. + */ +void +rpc_fromaddr(void *pkt, struct in_addr *addr, u_short *port) +{ + struct hackhdr { + /* Tail of IP header: just IP addresses */ + n_long ip_src; + n_long ip_dst; + /* UDP header: */ + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ + /* RPC reply header: */ + struct rpc_reply rpc; + } *hhdr; + + hhdr = ((struct hackhdr *)pkt) - 1; + addr->s_addr = hhdr->ip_src; + *port = hhdr->uh_sport; +} + +#ifdef NO_PMAP_CACHE +#define rpc_pmap_getcache(addr, prog, vers) (-1) +#define rpc_pmap_putcache(addr, prog, vers, port) +#else + +/* + * RPC Portmapper cache + */ +#define PMAP_NUM 8 /* need at most 5 pmap entries */ + +int rpc_pmap_num; +struct pmap_list { + struct in_addr addr; /* server, net order */ + u_int prog; /* host order */ + u_int vers; /* host order */ + int port; /* host order */ +} rpc_pmap_list[PMAP_NUM]; + +/* + * return port number in host order, or -1. + * arguments are: + * addr .. server, net order. + * prog .. host order. + * vers .. host order. + */ +int +rpc_pmap_getcache(struct in_addr addr, u_int prog, u_int vers) +{ + struct pmap_list *pl; + + for (pl = rpc_pmap_list; pl < &rpc_pmap_list[rpc_pmap_num]; pl++) { + if (pl->addr.s_addr == addr.s_addr && + pl->prog == prog && pl->vers == vers ) + { + return pl->port; + } + } + return -1; +} + +/* + * arguments are: + * addr .. server, net order. + * prog .. host order. + * vers .. host order. + * port .. host order. + */ +void +rpc_pmap_putcache(struct in_addr addr, u_int prog, u_int vers, int port) +{ + struct pmap_list *pl; + + /* Don't overflow cache... */ + if (rpc_pmap_num >= PMAP_NUM) { + /* ... just re-use the last entry. */ + rpc_pmap_num = PMAP_NUM - 1; +#ifdef RPC_DEBUG + printf("rpc_pmap_putcache: cache overflow\n"); +#endif + } + + pl = &rpc_pmap_list[rpc_pmap_num]; + rpc_pmap_num++; + + /* Cache answer */ + pl->addr = addr; + pl->prog = prog; + pl->vers = vers; + pl->port = port; +} +#endif + +/* + * Request a port number from the port mapper. + * Returns the port in host order. + * prog and vers are host order. + */ +int +rpc_getport(struct iodesc *d, n_long prog, n_long vers) +{ + struct args { + n_long prog; /* call program */ + n_long vers; /* call version */ + n_long proto; /* call protocol */ + n_long port; /* call port (unused) */ + } *args; + struct res { + n_long port; + } *res; + struct { + n_long h[RPC_HEADER_WORDS]; + struct args d; + } sdata; + struct { + n_long h[RPC_HEADER_WORDS]; + struct res d; + n_long pad; + } rdata; + ssize_t cc; + int port; + +#ifdef RPC_DEBUG + if (debug) + printf("getport: prog=0x%x vers=%d\n", prog, vers); +#endif + + /* This one is fixed forever. */ + if (prog == PMAPPROG) + return PMAPPORT; + + /* Try for cached answer first */ + port = rpc_pmap_getcache(d->destip, prog, vers); + if (port != -1) + return port; + + args = &sdata.d; + args->prog = htonl(prog); + args->vers = htonl(vers); + args->proto = htonl(IPPROTO_UDP); + args->port = 0; + res = &rdata.d; + + cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, + args, sizeof(*args), res, sizeof(*res)); + if ((size_t)cc < sizeof(*res)) { + printf("getport: %s", strerror(errno)); + errno = EBADRPC; + return -1; + } + port = (int)ntohl(res->port); + + rpc_pmap_putcache(d->destip, prog, vers, port); + + return port; +} diff --git a/sys/lib/libsa/rpc.h b/sys/lib/libsa/rpc.h new file mode 100644 index 000000000..756cdc80c --- /dev/null +++ b/sys/lib/libsa/rpc.h @@ -0,0 +1,69 @@ +/* $NetBSD: rpc.h,v 1.11 2009/01/17 14:00:36 tsutsui Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* XXX defines we can't easily get from system includes */ +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 + +/* RPC functions: */ +ssize_t rpc_call(struct iodesc *, n_long, n_long, n_long, void *, size_t, + void *, size_t); +void rpc_fromaddr(void *, struct in_addr *, u_short *); +int rpc_pmap_getcache(struct in_addr, u_int, u_int); +void rpc_pmap_putcache(struct in_addr, u_int, u_int, int); +int rpc_getport(struct iodesc *, n_long, n_long); + +extern int rpc_port; /* decrement before bind */ + +/* + * How much space to leave in front of RPC requests. + * In 32-bit words (alignment) we have: + * 12: Ether + IP + UDP + padding + * 6: RPC call header + * 7: Auth UNIX + * 2: Auth NULL + */ +#define RPC_HEADER_WORDS 28 diff --git a/sys/lib/libsa/rpcv2.h b/sys/lib/libsa/rpcv2.h new file mode 100644 index 000000000..43fd4bfb8 --- /dev/null +++ b/sys/lib/libsa/rpcv2.h @@ -0,0 +1,85 @@ +/* $NetBSD: rpcv2.h,v 1.3 2005/12/11 12:24:46 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rpcv2.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Definitions for Sun RPC Version 2, from + * "RPC: Remote Procedure Call Protocol Specification" RFC1057 + */ + +/* Version # */ +#define RPC_VER2 2 + +/* Authentication */ +#define RPCAUTH_NULL 0 +#define RPCAUTH_UNIX 1 +#define RPCAUTH_SHORT 2 +#define RPCAUTH_MAXSIZ 400 +#define RPCAUTH_UNIXGIDS 16 + +/* Rpc Constants */ +#define RPC_CALL 0 +#define RPC_REPLY 1 +#define RPC_MSGACCEPTED 0 +#define RPC_MSGDENIED 1 +#define RPC_PROGUNAVAIL 1 +#define RPC_PROGMISMATCH 2 +#define RPC_PROCUNAVAIL 3 +#define RPC_GARBAGE 4 /* I like this one */ +#define RPC_MISMATCH 0 +#define RPC_AUTHERR 1 + +/* Authentication failures */ +#define AUTH_BADCRED 1 +#define AUTH_REJECTCRED 2 +#define AUTH_BADVERF 3 +#define AUTH_REJECTVERF 4 +#define AUTH_TOOWEAK 5 /* Give em wheaties */ + +/* Sizes of rpc header parts */ +#define RPC_SIZ 24 +#define RPC_REPLYSIZ 28 + +/* RPC Prog definitions */ +#define RPCPROG_MNT 100005 +#define RPCMNT_VER1 1 +#define RPCMNT_MOUNT 1 +#define RPCMNT_DUMP 2 +#define RPCMNT_UMOUNT 3 +#define RPCMNT_UMNTALL 4 +#define RPCMNT_EXPORT 5 +#define RPCMNT_NAMELEN 255 +#define RPCMNT_PATHLEN 1024 +#define RPCPROG_NFS 100003 diff --git a/sys/lib/libsa/saerrno.h b/sys/lib/libsa/saerrno.h new file mode 100644 index 000000000..f0a70fb7d --- /dev/null +++ b/sys/lib/libsa/saerrno.h @@ -0,0 +1,51 @@ +/* $NetBSD: saerrno.h,v 1.11 2007/12/03 09:51:31 isaki Exp $ */ + +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)saerrno.h 8.1 (Berkeley) 6/11/93 + */ + +#include + +extern int errno; + +/* special stand error codes */ +#define EADAPT (ELAST+1) /* bad adaptor */ +#define ECTLR (ELAST+2) /* bad controller */ +#define EUNIT (ELAST+3) /* bad drive */ +#define EPART (ELAST+4) /* bad partition */ +#define ERDLAB (ELAST+5) /* can't read disk label */ +#define EUNLAB (ELAST+6) /* unlabeled disk */ +#define EOFFSET (ELAST+7) /* relative seek not supported */ +#define ECMD (ELAST+8) /* undefined driver command */ +#define EBSE (ELAST+9) /* bad sector error */ +#define EWCK (ELAST+10) /* write check error */ +#define EECC (ELAST+11) /* uncorrectable ecc error */ +#define EHER (ELAST+12) /* hard error */ +#define ESALAST (ELAST+12) /* */ diff --git a/sys/lib/libsa/saioctl.h b/sys/lib/libsa/saioctl.h new file mode 100644 index 000000000..8b0198a6a --- /dev/null +++ b/sys/lib/libsa/saioctl.h @@ -0,0 +1,48 @@ +/* $NetBSD: saioctl.h,v 1.4 2005/12/11 12:24:46 christos Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)saioctl.h 8.1 (Berkeley) 6/11/93 + */ + +/* ioctl's -- for disks just now */ +#define SAIOHDR (('d'<<8)|1) /* next i/o includes header */ +#define SAIOCHECK (('d'<<8)|2) /* next i/o checks data */ +#define SAIOHCHECK (('d'<<8)|3) /* next i/o checks header & data */ +#define SAIONOBAD (('d'<<8)|4) /* inhibit bad sector forwarding */ +#define SAIODOBAD (('d'<<8)|5) /* enable bad sector forwarding */ +#define SAIOECCLIM (('d'<<8)|6) /* set limit to ecc correction, bits */ +#define SAIOECCUNL (('d'<<8)|7) /* use standard ecc procedures */ +#define SAIORETRIES (('d'<<8)|8) /* set retry count for unit */ +#define SAIODEVDATA (('d'<<8)|9) /* get pointer to pack label */ +#define SAIOSSI (('d'<<8)|10) /* set skip sector inhibit */ +#define SAIONOSSI (('d'<<8)|11) /* inhibit skip sector handling */ +#define SAIOSSDEV (('d'<<8)|12) /* is device skip sector type? */ +#define SAIODEBUG (('d'<<8)|13) /* enable/disable debugging */ +#define SAIOGBADINFO (('d'<<8)|14) /* get bad-sector table */ diff --git a/sys/lib/libsa/snprintf.c b/sys/lib/libsa/snprintf.c new file mode 100644 index 000000000..f5ccf9735 --- /dev/null +++ b/sys/lib/libsa/snprintf.c @@ -0,0 +1,50 @@ +/* $NetBSD: snprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include +#include + +#include "stand.h" + +int +snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, size, fmt, ap); + va_end(ap); + return len; +} diff --git a/sys/lib/libsa/sprintf.c b/sys/lib/libsa/sprintf.c new file mode 100644 index 000000000..a34e59e7b --- /dev/null +++ b/sys/lib/libsa/sprintf.c @@ -0,0 +1,49 @@ +/* $NetBSD: sprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +#include "stand.h" + +int +sprintf(char *buf, const char *fmt, ...) +{ + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, -(size_t)buf, fmt, ap); + va_end(ap); + return len; +} diff --git a/sys/lib/libsa/stand.h b/sys/lib/libsa/stand.h new file mode 100644 index 000000000..a9d57200b --- /dev/null +++ b/sys/lib/libsa/stand.h @@ -0,0 +1,327 @@ +/* $NetBSD: stand.h,v 1.74 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* + * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stand.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _LIBSA_STAND_H_ +#define _LIBSA_STAND_H_ + +#include +#include +#include +#include +#include "saioctl.h" +#include "saerrno.h" + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef LIBSA_RENAME_PRINTF +#define getchar libsa_getchar +#define gets libsa_gets +#define printf libsa_printf +#define putchar libsa_putchar +#define sprintf libsa_sprintf +#define vprintf libsa_vprintf +#define vsprintf libsa_vsprintf +#endif + +struct open_file; + +#define FS_DEF_BASE(fs) \ + extern __compactcall int __CONCAT(fs,_open)(const char *, struct open_file *); \ + extern __compactcall int __CONCAT(fs,_close)(struct open_file *); \ + extern __compactcall int __CONCAT(fs,_read)(struct open_file *, void *, \ + size_t, size_t *); \ + extern __compactcall int __CONCAT(fs,_write)(struct open_file *, void *, \ + size_t, size_t *); \ + extern __compactcall off_t __CONCAT(fs,_seek)(struct open_file *, off_t, int); \ + extern __compactcall int __CONCAT(fs,_stat)(struct open_file *, struct stat *) + +#if defined(LIBSA_ENABLE_LS_OP) +#define FS_DEF(fs) \ + FS_DEF_BASE(fs);\ + extern __compactcall void __CONCAT(fs,_ls)(struct open_file *, const char *) +#else +#define FS_DEF(fs) FS_DEF_BASE(fs) +#endif + + +/* + * This structure is used to define file system operations in a file system + * independent way. + */ +extern char *fsmod; +extern char *fsmod2; + +#if !defined(LIBSA_SINGLE_FILESYSTEM) +struct fs_ops { + __compactcall int (*open)(const char *, struct open_file *); + __compactcall int (*close)(struct open_file *); + __compactcall int (*read)(struct open_file *, void *, size_t, size_t *); + __compactcall int (*write)(struct open_file *, void *, size_t size, size_t *); + __compactcall off_t (*seek)(struct open_file *, off_t, int); + __compactcall int (*stat)(struct open_file *, struct stat *); +#if defined(LIBSA_ENABLE_LS_OP) + __compactcall void (*ls)(struct open_file *, const char *); +#endif +}; + +extern struct fs_ops file_system[]; +extern int nfsys; + +#if defined(LIBSA_ENABLE_LS_OP) +#define FS_OPS(fs) { \ + __CONCAT(fs,_open), \ + __CONCAT(fs,_close), \ + __CONCAT(fs,_read), \ + __CONCAT(fs,_write), \ + __CONCAT(fs,_seek), \ + __CONCAT(fs,_stat), \ + __CONCAT(fs,_ls) } +#else +#define FS_OPS(fs) { \ + __CONCAT(fs,_open), \ + __CONCAT(fs,_close), \ + __CONCAT(fs,_read), \ + __CONCAT(fs,_write), \ + __CONCAT(fs,_seek), \ + __CONCAT(fs,_stat) } +#endif + +#define FS_OPEN(fs) ((fs)->open) +#define FS_CLOSE(fs) ((fs)->close) +#define FS_READ(fs) ((fs)->read) +#define FS_WRITE(fs) ((fs)->write) +#define FS_SEEK(fs) ((fs)->seek) +#define FS_STAT(fs) ((fs)->stat) +#if defined(LIBSA_ENABLE_LS_OP) +#define FS_LS(fs) ((fs)->ls) +#endif + +#else + +#define FS_OPEN(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_open) +#define FS_CLOSE(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_close) +#define FS_READ(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_read) +#define FS_WRITE(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_write) +#define FS_SEEK(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_seek) +#define FS_STAT(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_stat) +#if defined(LIBSA_ENABLE_LS_OP) +#define FS_LS(fs) ___CONCAT(LIBSA_SINGLE_FILESYSTEM,_ls) +#endif + +FS_DEF(LIBSA_SINGLE_FILESYSTEM); + +#endif + +/* where values for lseek(2) */ +#define SEEK_SET 0 /* set file offset to offset */ +#define SEEK_CUR 1 /* set file offset to current plus offset */ +#define SEEK_END 2 /* set file offset to EOF plus offset */ + +/* Device switch */ +#if !defined(LIBSA_SINGLE_DEVICE) + +struct devsw { + char *dv_name; + int (*dv_strategy)(void *, int, daddr_t, size_t, void *, size_t *); + int (*dv_open)(struct open_file *, ...); + int (*dv_close)(struct open_file *); + int (*dv_ioctl)(struct open_file *, u_long, void *); +}; + +extern struct devsw devsw[]; /* device array */ +extern int ndevs; /* number of elements in devsw[] */ + +#define DEV_NAME(d) ((d)->dv_name) +#define DEV_STRATEGY(d) ((d)->dv_strategy) +#define DEV_OPEN(d) ((d)->dv_open) +#define DEV_CLOSE(d) ((d)->dv_close) +#define DEV_IOCTL(d) ((d)->dv_ioctl) + +#else + +#define DEV_NAME(d) ___STRING(LIBSA_SINGLE_DEVICE) +#define DEV_STRATEGY(d) ___CONCAT(LIBSA_SINGLE_DEVICE,strategy) +#define DEV_OPEN(d) ___CONCAT(LIBSA_SINGLE_DEVICE,open) +#define DEV_CLOSE(d) ___CONCAT(LIBSA_SINGLE_DEVICE,close) +#define DEV_IOCTL(d) ___CONCAT(LIBSA_SINGLE_DEVICE,ioctl) + +/* These may be #defines which must not be expanded here, hence the extra () */ +int (DEV_STRATEGY(unused))(void *, int, daddr_t, size_t, void *, size_t *); +int (DEV_OPEN(unused))(struct open_file *, ...); +int (DEV_CLOSE(unused))(struct open_file *); +int (DEV_IOCTL(unused))(struct open_file *, u_long, void *); + +#endif + +struct open_file { + int f_flags; /* see F_* below */ +#if !defined(LIBSA_SINGLE_DEVICE) + const struct devsw *f_dev; /* pointer to device operations */ +#endif + void *f_devdata; /* device specific data */ +#if !defined(LIBSA_SINGLE_FILESYSTEM) + const struct fs_ops *f_ops; /* pointer to file system operations */ +#endif + void *f_fsdata; /* file system specific data */ +#if !defined(LIBSA_NO_RAW_ACCESS) + off_t f_offset; /* current file offset (F_RAW) */ +#endif +}; + +#define SOPEN_MAX 4 +extern struct open_file files[]; + +/* f_flags values */ +#define F_READ 0x0001 /* file opened for reading */ +#define F_WRITE 0x0002 /* file opened for writing */ +#if !defined(LIBSA_NO_RAW_ACCESS) +#define F_RAW 0x0004 /* raw device open - no file system */ +#endif +#define F_NODEV 0x0008 /* network open - no device */ + +int (devopen)(struct open_file *, const char *, char **); +#ifdef HEAP_VARIABLE +void setheap(void *, void *); +#endif +void *alloc(size_t) __compactcall; +void dealloc(void *, size_t) __compactcall; +struct disklabel; +char *getdisklabel(const char *, struct disklabel *); +int dkcksum(const struct disklabel *); + +void printf(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +int sprintf(char *, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +int snprintf(char *, size_t, const char *, ...) + __attribute__((__format__(__printf__, 3, 4))); +void vprintf(const char *, va_list) + __attribute__((__format__(__printf__, 1, 0))); +int vsprintf(char *, const char *, va_list) + __attribute__((__format__(__printf__, 2, 0))); +int vsnprintf(char *, size_t, const char *, va_list) + __attribute__((__format__(__printf__, 3, 0))); +void twiddle(void); +void gets(char *); +int getfile(char *prompt, int mode); +char *strerror(int); +__dead void exit(int); +__dead void panic(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +__dead void _rtt(void); +void *memcpy(void *, const void *, size_t); +void *memmove(void *, const void *, size_t); +int memcmp(const void *, const void *, size_t); +void *memset(void *, int, size_t); +void exec(char *, char *, int); +int open(const char *, int); +int close(int); +void closeall(void); +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +off_t lseek(int, off_t, int); +int ioctl(int, u_long, char *); +int stat(const char *, struct stat *); +int fstat(int, struct stat *); +#if defined(LIBSA_ENABLE_LS_OP) +void ls(const char *); +#endif + +typedef int cmp_t(const void *, const void *); +void qsort(void *, size_t, size_t, cmp_t *); + +extern int opterr, optind, optopt, optreset; +extern char *optarg; +int getopt(int, char * const *, const char *); + +char *getpass(const char *); +int checkpasswd(void); +int check_password(const char *); + +int nodev(void); +int noioctl(struct open_file *, u_long, void *); +void nullsys(void); + +FS_DEF(null); + +/* Machine dependent functions */ +void machdep_start(char *, int, char *, char *, char *); +int getchar(void); +void putchar(int); + +#ifdef __INTERNAL_LIBSA_CREAD +int oopen(const char *, int); +int oclose(int); +ssize_t oread(int, void *, size_t); +off_t olseek(int, off_t, int); +#endif + +extern const char hexdigits[]; + +/* XXX: These should be removed eventually. */ +void bcopy(const void *, void *, size_t); +void bzero(void *, size_t); + +#endif /* _LIBSA_STAND_H_ */ diff --git a/sys/lib/libsa/stat.c b/sys/lib/libsa/stat.c new file mode 100644 index 000000000..3387e809f --- /dev/null +++ b/sys/lib/libsa/stat.c @@ -0,0 +1,47 @@ +/* $NetBSD: stat.c,v 1.7 2007/11/24 13:20:57 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stat.c 8.1 (Berkeley) 6/11/93 + */ + +#include "stand.h" + +int +stat(const char *str, struct stat *sb) +{ + int fd, rv; + + fd = open(str, 0); + if (fd < 0) + return -1; + rv = fstat(fd, sb); + (void)close(fd); + return rv; +} diff --git a/sys/lib/libsa/strerror.c b/sys/lib/libsa/strerror.c new file mode 100644 index 000000000..3e03aba47 --- /dev/null +++ b/sys/lib/libsa/strerror.c @@ -0,0 +1,72 @@ +/* $NetBSD: strerror.c,v 1.20 2007/11/24 13:20:57 isaki Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "saerrno.h" +#include "stand.h" + +static const struct mi { + int errno; + const char *msg; +} errlist[] = { + { EADAPT, "bad adaptor number" }, + { ECTLR, "bad controller number" }, + { EUNIT, "bad drive number" }, + { EPART, "bad partition" }, + { ERDLAB, "can't read disk label" }, + { EUNLAB, "unlabeled" }, + { ENXIO, "Device not configured" }, + { EPERM, "Operation not permitted" }, + { ENOENT, "No such file or directory" }, + { ESTALE, "Stale NFS file handle" }, + { EFTYPE, "Inappropriate file type or format" }, + { ENOEXEC, "Exec format error" }, + { EIO, "Input/output error" }, + { EINVAL, "Invalid argument" }, + { ENOTDIR, "Not a directory" }, + { EOFFSET, "invalid file offset" }, + { EACCES, "Permission denied" }, + { 0, 0 }, +}; + +char * +strerror(int err) +{ + static char ebuf[36]; + const struct mi *mi; + + for (mi = errlist; mi->msg; mi++) + if (mi->errno == err) + return __UNCONST(mi->msg); + + snprintf(ebuf, sizeof ebuf, "Unknown error: code %d", err); + return ebuf; +} diff --git a/sys/lib/libsa/subr_prf.c b/sys/lib/libsa/subr_prf.c new file mode 100644 index 000000000..e464890c2 --- /dev/null +++ b/sys/lib/libsa/subr_prf.c @@ -0,0 +1,332 @@ +/* $NetBSD: subr_prf.c,v 1.21 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +/* + * Scaled down version of printf(3). + */ + +#include +#include +#include /* XXX: for intptr_t */ + +#include "stand.h" + +#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT +#define INTMAX_T longlong_t +#define UINTMAX_T u_longlong_t +#else +#define INTMAX_T long +#define UINTMAX_T u_long +#endif + +#if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */ +#define PTRDIFF_T ptrdiff_t +#else +#define PTRDIFF_T intptr_t +#endif + +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT +static void kprintn(void (*)(int), UINTMAX_T, int, int, int); +#else +static void kprintn(void (*)(int), UINTMAX_T, int); +#endif +static void sputchar(int); +static void kdoprnt(void (*)(int), const char *, va_list); + +static char *sbuf, *ebuf; + +const char hexdigits[16] = "0123456789abcdef"; + +#define LONG 0x01 +#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT +#define LLONG 0x02 +#endif +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT +#define ALT 0x04 +#define SPACE 0x08 +#define LADJUST 0x10 +#define SIGN 0x20 +#define ZEROPAD 0x40 +#define NEGATIVE 0x80 +#define KPRINTN(base) kprintn(put, ul, base, lflag, width) +#define RZERO() \ +do { \ + if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) { \ + while (width-- > 0) \ + put('0'); \ + } \ +} while (/*CONSTCOND*/0) +#define RPAD() \ +do { \ + if (lflag & LADJUST) { \ + while (width-- > 0) \ + put(' '); \ + } \ +} while (/*CONSTCOND*/0) +#define LPAD() \ +do { \ + if ((lflag & (ZEROPAD|LADJUST)) == 0) { \ + while (width-- > 0) \ + put(' '); \ + } \ +} while (/*CONSTCOND*/0) +#else /* LIBSA_PRINTF_WIDTH_SUPPORT */ +#define KPRINTN(base) kprintn(put, ul, base) +#define RZERO() /**/ +#define RPAD() /**/ +#define LPAD() /**/ +#endif /* LIBSA_PRINTF_WIDTH_SUPPORT */ + +#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT +#define KPRINT(base) \ +do { \ + ul = (lflag & LLONG) \ + ? va_arg(ap, u_longlong_t) \ + : (lflag & LONG) \ + ? va_arg(ap, u_long) \ + : va_arg(ap, u_int); \ + KPRINTN(base); \ +} while (/*CONSTCOND*/0) +#else /* LIBSA_PRINTF_LONGLONG_SUPPORT */ +#define KPRINT(base) \ +do { \ + ul = (lflag & LONG) \ + ? va_arg(ap, u_long) : va_arg(ap, u_int); \ + KPRINTN(base); \ +} while (/*CONSTCOND*/0) +#endif /* LIBSA_PRINTF_LONGLONG_SUPPORT */ + +static void +sputchar(int c) +{ + + if (sbuf < ebuf) + *sbuf++ = c; +} + +void +vprintf(const char *fmt, va_list ap) +{ + + kdoprnt(putchar, fmt, ap); +} + +int +vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) +{ + + sbuf = buf; + ebuf = buf + size - 1; + kdoprnt(sputchar, fmt, ap); + *sbuf = '\0'; + return sbuf - buf; +} + +static void +kdoprnt(void (*put)(int), const char *fmt, va_list ap) +{ + char *p; + int ch; + UINTMAX_T ul; + int lflag; +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + int width; + char *q; +#endif + + for (;;) { + while ((ch = *fmt++) != '%') { + if (ch == '\0') + return; + put(ch); + } + lflag = 0; +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + width = 0; +#endif +reswitch: + switch (ch = *fmt++) { +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + case '#': + lflag |= ALT; + goto reswitch; + case ' ': + lflag |= SPACE; + goto reswitch; + case '-': + lflag |= LADJUST; + goto reswitch; + case '+': + lflag |= SIGN; + goto reswitch; + case '0': + lflag |= ZEROPAD; + goto reswitch; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + for (;;) { + width *= 10; + width += ch - '0'; + ch = *fmt; + if ((unsigned)ch - '0' > 9) + break; + ++fmt; + } +#endif + goto reswitch; + case 'l': +#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT + if (*fmt == 'l') { + ++fmt; + lflag |= LLONG; + } else +#endif + lflag |= LONG; + goto reswitch; + case 't': + if (sizeof(PTRDIFF_T) == sizeof(long)) + lflag |= LONG; + goto reswitch; + case 'z': + if (sizeof(ssize_t) == sizeof(long)) + lflag |= LONG; + goto reswitch; + case 'c': + ch = va_arg(ap, int); +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + --width; +#endif + RPAD(); + put(ch & 0xFF); + LPAD(); + break; + case 's': + p = va_arg(ap, char *); +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + for (q = p; *q != '\0'; ++q) + continue; + width -= q - p; +#endif + RPAD(); + while ((ch = (unsigned char)*p++)) + put(ch); + LPAD(); + break; + case 'd': + ul = +#ifdef LIBSA_PRINTF_LONGLONG_SUPPORT + (lflag & LLONG) ? va_arg(ap, longlong_t) : +#endif + (lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int); + if ((INTMAX_T)ul < 0) { + ul = -(INTMAX_T)ul; +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + lflag |= NEGATIVE; +#else + put('-'); +#endif + } + KPRINTN(10); + break; + case 'o': + KPRINT(8); + break; + case 'u': + KPRINT(10); + break; + case 'p': +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + lflag |= (LONG|ALT); +#else + put('0'); + put('x'); +#endif + /* FALLTHROUGH */ + case 'x': + KPRINT(16); + break; + default: + if (ch == '\0') + return; + put(ch); + break; + } + } +} + +static void +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT +kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width) +#else +kprintn(void (*put)(int), UINTMAX_T ul, int base) +#endif +{ + /* hold a INTMAX_T in base 8 */ + char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */]; +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + char *q; +#endif + + p = buf; + do { + *p++ = hexdigits[ul % base]; + } while (ul /= base); +#ifdef LIBSA_PRINTF_WIDTH_SUPPORT + q = p; + if (lflag & ALT && *(p - 1) != '0') { + if (base == 8) { + *p++ = '0'; + } else if (base == 16) { + *p++ = 'x'; + *p++ = '0'; + } + } + if (lflag & NEGATIVE) + *p++ = '-'; + else if (lflag & SIGN) + *p++ = '+'; + else if (lflag & SPACE) + *p++ = ' '; + width -= p - buf; + if ((lflag & LADJUST) == 0) { + while (p > q) + put(*--p); + } +#endif + RPAD(); + RZERO(); + do { + put(*--p); + } while (p > buf); + LPAD(); +} diff --git a/sys/lib/libsa/tftp.c b/sys/lib/libsa/tftp.c new file mode 100644 index 000000000..f6a025d44 --- /dev/null +++ b/sys/lib/libsa/tftp.c @@ -0,0 +1,459 @@ +/* $NetBSD: tftp.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Simple TFTP implementation for libsa. + * Assumes: + * - socket descriptor (int) at open_file->f_devdata + * - server host IP in global servip + * Restrictions: + * - read only + * - lseek only with SEEK_SET or SEEK_CUR + * - no big time differences between transfers ( +#include +#include +#include +#include +#include + +#include "stand.h" +#include "net.h" + +#include "tftp.h" + +extern struct in_addr servip; + +static int tftpport = 2000; + +#define RSPACE 520 /* max data packet, rounded up */ + +struct tftp_handle { + struct iodesc *iodesc; + int currblock; /* contents of lastdata */ + int islastblock; /* flag */ + int validsize; + int off; + const char *path; /* saved for re-requests */ + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct tftphdr t; + u_char space[RSPACE]; + } lastdata; +}; + +static const int tftperrors[8] = { + 0, /* ??? */ + ENOENT, + EPERM, + ENOSPC, + EINVAL, /* ??? */ + EINVAL, /* ??? */ + EEXIST, + EINVAL, /* ??? */ +}; + +static ssize_t recvtftp(struct iodesc *, void *, size_t, saseconds_t); +static int tftp_makereq(struct tftp_handle *); +static int tftp_getnextblock(struct tftp_handle *); +#ifndef TFTP_NOTERMINATE +static void tftp_terminate(struct tftp_handle *); +#endif +static ssize_t tftp_size_of_file(struct tftp_handle *tftpfile); + +static ssize_t +recvtftp(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + ssize_t n; + struct tftphdr *t; + + errno = 0; + + n = readudp(d, pkt, len, tleft); + + if (n < 4) + return -1; + + t = (struct tftphdr *)pkt; + switch (ntohs(t->th_opcode)) { + case DATA: + if (htons(t->th_block) != d->xid) { + /* + * Expected block? + */ + return -1; + } + if (d->xid == 1) { + /* + * First data packet from new port. + */ + struct udphdr *uh; + uh = (struct udphdr *)pkt - 1; + d->destport = uh->uh_sport; + } /* else check uh_sport has not changed??? */ + return (n - (t->th_data - (char *)t)); + case ERROR: + if ((unsigned int)ntohs(t->th_code) >= 8) { + printf("illegal tftp error %d\n", ntohs(t->th_code)); + errno = EIO; + } else { +#ifdef DEBUG + printf("tftp-error %d\n", ntohs(t->th_code)); +#endif + errno = tftperrors[ntohs(t->th_code)]; + } + return -1; + default: +#ifdef DEBUG + printf("tftp type %d not handled\n", ntohs(t->th_opcode)); +#endif + return -1; + } +} + +/* send request, expect first block (or error) */ +static int +tftp_makereq(struct tftp_handle *h) +{ + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct tftphdr t; + u_char space[FNAME_SIZE + 6]; + } wbuf; + char *wtail; + int l; + ssize_t res; + struct tftphdr *t; + + wbuf.t.th_opcode = htons((u_short)RRQ); + wtail = wbuf.t.th_stuff; + l = strlen(h->path); + (void)memcpy(wtail, h->path, l + 1); + wtail += l + 1; + (void)memcpy(wtail, "octet", 6); + wtail += 6; + + t = &h->lastdata.t; + + /* h->iodesc->myport = htons(--tftpport); */ + h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff)); + h->iodesc->destport = htons(IPPORT_TFTP); + h->iodesc->xid = 1; /* expected block */ + + res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *)&wbuf.t, + recvtftp, t, sizeof(*t) + RSPACE); + + if (res == -1) + return errno; + + h->currblock = 1; + h->validsize = res; + h->islastblock = 0; + if (res < SEGSIZE) + h->islastblock = 1; /* very short file */ + return 0; +} + +/* ack block, expect next */ +static int +tftp_getnextblock(struct tftp_handle *h) +{ + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct tftphdr t; + } wbuf; + char *wtail; + int res; + struct tftphdr *t; + + wbuf.t.th_opcode = htons((u_short)ACK); + wbuf.t.th_block = htons((u_short)h->currblock); + wtail = (char *)&wbuf.t.th_data; + + t = &h->lastdata.t; + + h->iodesc->xid = h->currblock + 1; /* expected block */ + + res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *)&wbuf.t, + recvtftp, t, sizeof(*t) + RSPACE); + + if (res == -1) /* 0 is OK! */ + return errno; + + h->currblock++; + h->validsize = res; + if (res < SEGSIZE) + h->islastblock = 1; /* EOF */ + return 0; +} + +#ifndef TFTP_NOTERMINATE +static void +tftp_terminate(struct tftp_handle *h) +{ + struct { + u_char header[UDP_TOTAL_HEADER_SIZE]; + struct tftphdr t; + } wbuf; + char *wtail; + + wtail = (char *)&wbuf.t.th_data; + if (h->islastblock) { + wbuf.t.th_opcode = htons((u_short)ACK); + wbuf.t.th_block = htons((u_short)h->currblock); + } else { + wbuf.t.th_opcode = htons((u_short)ERROR); + wbuf.t.th_code = htons((u_short)ENOSPACE); /* ??? */ + *wtail++ = '\0'; /* empty error string */ + } + + (void)sendudp(h->iodesc, &wbuf.t, wtail - (char *)&wbuf.t); +} +#endif + +__compactcall int +tftp_open(const char *path, struct open_file *f) +{ + struct tftp_handle *tftpfile; + struct iodesc *io; + int res; + + tftpfile = (struct tftp_handle *)alloc(sizeof(*tftpfile)); + if (!tftpfile) + return ENOMEM; + + tftpfile->iodesc = io = socktodesc(*(int *)(f->f_devdata)); + io->destip = servip; + tftpfile->off = 0; + tftpfile->path = path; /* XXXXXXX we hope it's static */ + + res = tftp_makereq(tftpfile); + + if (res) { + dealloc(tftpfile, sizeof(*tftpfile)); + return res; + } + f->f_fsdata = (void *)tftpfile; + fsmod = "nfs"; + return 0; +} + +__compactcall int +tftp_read(struct open_file *f, void *addr, size_t size, size_t *resid) +{ + struct tftp_handle *tftpfile; +#if !defined(LIBSA_NO_TWIDDLE) + static int tc = 0; +#endif + tftpfile = (struct tftp_handle *)f->f_fsdata; + + while (size > 0) { + int needblock; + size_t count; + +#if !defined(LIBSA_NO_TWIDDLE) + if (!(tc++ % 16)) + twiddle(); +#endif + + needblock = tftpfile->off / SEGSIZE + 1; + + if (tftpfile->currblock > needblock) { /* seek backwards */ +#ifndef TFTP_NOTERMINATE + tftp_terminate(tftpfile); +#endif + tftp_makereq(tftpfile); /* no error check, it worked + * for open */ + } + + while (tftpfile->currblock < needblock) { + int res; + + res = tftp_getnextblock(tftpfile); + if (res) { /* no answer */ +#ifdef DEBUG + printf("tftp: read error (block %d->%d)\n", + tftpfile->currblock, needblock); +#endif + return res; + } + if (tftpfile->islastblock) + break; + } + + if (tftpfile->currblock == needblock) { + size_t offinblock, inbuffer; + + offinblock = tftpfile->off % SEGSIZE; + + if (offinblock > tftpfile->validsize) { +#ifdef DEBUG + printf("tftp: invalid offset %d\n", + tftpfile->off); +#endif + return EINVAL; + } + inbuffer = tftpfile->validsize - offinblock; + count = (size < inbuffer ? size : inbuffer); + (void)memcpy(addr, + tftpfile->lastdata.t.th_data + offinblock, + count); + + addr = (char *)addr + count; + tftpfile->off += count; + size -= count; + + if ((tftpfile->islastblock) && (count == inbuffer)) + break; /* EOF */ + } else { +#ifdef DEBUG + printf("tftp: block %d not found\n", needblock); +#endif + return EINVAL; + } + + } + + if (resid) + *resid = size; + return 0; +} + +__compactcall int +tftp_close(struct open_file *f) +{ + struct tftp_handle *tftpfile; + tftpfile = (struct tftp_handle *)f->f_fsdata; + +#ifdef TFTP_NOTERMINATE + /* let it time out ... */ +#else + tftp_terminate(tftpfile); +#endif + + dealloc(tftpfile, sizeof(*tftpfile)); + return 0; +} + +__compactcall int +tftp_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} + +static ssize_t +tftp_size_of_file(struct tftp_handle *tftpfile) +{ + ssize_t filesize; + + if (tftpfile->currblock > 1) { /* move to start of file */ +#ifndef TFTP_NOTERMINATE + tftp_terminate(tftpfile); +#endif + tftp_makereq(tftpfile); /* no error check, it worked + * for open */ + } + + /* start with the size of block 1 */ + filesize = tftpfile->validsize; + + /* and keep adding the sizes till we hit the last block */ + while (!tftpfile->islastblock) { + int res; + + res = tftp_getnextblock(tftpfile); + if (res) { /* no answer */ +#ifdef DEBUG + printf("tftp: read error (block %d)\n", + tftpfile->currblock); +#endif + return -1; + } + filesize += tftpfile->validsize; + } +#ifdef DEBUG + printf("tftp_size_of_file: file is %zu bytes\n", filesize); +#endif + return filesize; +} + +__compactcall int +tftp_stat(struct open_file *f, struct stat *sb) +{ + struct tftp_handle *tftpfile; + tftpfile = (struct tftp_handle *)f->f_fsdata; + + sb->st_mode = 0444; + sb->st_nlink = 1; + sb->st_uid = 0; + sb->st_gid = 0; + sb->st_size = tftp_size_of_file(tftpfile); + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +tftp_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by tftp\n"); + return; +} +#endif + +__compactcall off_t +tftp_seek(struct open_file *f, off_t offset, int where) +{ + struct tftp_handle *tftpfile; + tftpfile = (struct tftp_handle *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + tftpfile->off = offset; + break; + case SEEK_CUR: + tftpfile->off += offset; + break; + default: + errno = EOFFSET; + return -1; + } + return tftpfile->off; +} diff --git a/sys/lib/libsa/tftp.h b/sys/lib/libsa/tftp.h new file mode 100644 index 000000000..4be48f9b5 --- /dev/null +++ b/sys/lib/libsa/tftp.h @@ -0,0 +1,104 @@ +/* $NetBSD: tftp.h,v 1.6 2005/12/11 12:24:46 christos Exp $ */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* NetBSD: tftp.h,v 1.6 2000/10/18 01:35:46 dogcow Exp */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tftp.h 8.1 (Berkeley) 6/2/93 + */ +/* + * Trivial File Transfer Protocol (IEN-133) + */ +#define SEGSIZE 512 /* data segment size */ + +/* + * Packet types. + */ +#define RRQ 01 /* read request */ +#define WRQ 02 /* write request */ +#define DATA 03 /* data packet */ +#define ACK 04 /* acknowledgement */ +#define ERROR 05 /* error code */ + +struct tftphdr { + short th_opcode; /* packet type */ + union { + unsigned short tu_block; /* block # */ + short tu_code; /* error code */ + char tu_stuff[1]; /* request packet stuff */ + } th_u; + char th_data[1]; /* data or error string */ +}; + +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data + +/* + * Error codes. + */ +#define EUNDEF 0 /* not defined */ +#define ENOTFOUND 1 /* file not found */ +#define EACCESS 2 /* access violation */ +#define ENOSPACE 3 /* disk full or allocation exceeded */ +#define EBADOP 4 /* illegal TFTP operation */ +#define EBADID 5 /* unknown transfer ID */ +#define EEXISTS 6 /* file already exists */ +#define ENOUSER 7 /* no such user */ + +FS_DEF(tftp); + +#define IPPORT_TFTP 69 diff --git a/sys/lib/libsa/twiddle.c b/sys/lib/libsa/twiddle.c new file mode 100644 index 000000000..7189adb3f --- /dev/null +++ b/sys/lib/libsa/twiddle.c @@ -0,0 +1,52 @@ +/* $NetBSD: twiddle.c,v 1.8 2008/04/30 16:18:09 ad Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +#include "stand.h" + +#define TWIDDLE_CHARS "|/-\\" + +char twiddle_toggle; + +void +twiddle(void) +{ + static int pos; + + if (!twiddle_toggle) { + putchar(TWIDDLE_CHARS[pos++ & 3]); + putchar('\b'); + } +} diff --git a/sys/lib/libsa/udp.c b/sys/lib/libsa/udp.c new file mode 100644 index 000000000..59668395c --- /dev/null +++ b/sys/lib/libsa/udp.c @@ -0,0 +1,136 @@ +/* $NetBSD: udp.c,v 1.11 2011/05/11 16:23:40 zoltan Exp $ */ + +/* + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include +#include + +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "stand.h" +#include "net.h" + + +/* Caller must leave room for ethernet, ip and udp headers in front!! */ +ssize_t +sendudp(struct iodesc *d, void *pkt, size_t len) +{ + ssize_t cc; + struct udphdr *uh; + +#ifdef NET_DEBUG + if (debug) { + printf("sendudp: d=%lx called.\n", (long)d); + if (d) { + printf("saddr: %s:%d", + inet_ntoa(d->myip), ntohs(d->myport)); + printf(" daddr: %s:%d\n", + inet_ntoa(d->destip), ntohs(d->destport)); + } + } +#endif + + uh = (struct udphdr *)pkt - 1; + len += sizeof(*uh); + + (void)memset(uh, 0, sizeof(*uh)); + + uh->uh_sport = d->myport; + uh->uh_dport = d->destport; + uh->uh_ulen = htons(len); + + cc = sendip(d, uh, len, IPPROTO_UDP); + if (cc == -1) + return -1; + if ((size_t)cc != len) + panic("sendudp: bad write (%zd != %zu)", cc, len); + return (cc - sizeof(*uh)); +} + +/* + * Receive a UDP packet and validate it is for us. + * Caller leaves room for the headers (Ether, IP, UDP) + */ +ssize_t +readudp(struct iodesc *d, void *pkt, size_t len, saseconds_t tleft) +{ + ssize_t n; + struct udphdr *uh; + + uh = (struct udphdr *)pkt - 1; + n = readip(d, uh, len + sizeof(*uh), tleft, IPPROTO_UDP); + if (n == -1 || (size_t)n < sizeof(*uh)) + return -1; + + if (uh->uh_dport != d->myport) { +#ifdef NET_DEBUG + if (debug) + printf("readudp: bad dport %d != %d\n", + d->myport, ntohs(uh->uh_dport)); +#endif + return -1; + } + + if (ntohs(uh->uh_ulen) < sizeof(*uh)) { +#ifdef NET_DEBUG + if (debug) + printf("readudp: bad udp len %d < %d\n", + ntohs(uh->uh_ulen), (int)sizeof(*uh)); +#endif + return -1; + } + + n -= sizeof(*uh); + return n; +} diff --git a/sys/lib/libsa/ufs.c b/sys/lib/libsa/ufs.c new file mode 100644 index 000000000..63be30be6 --- /dev/null +++ b/sys/lib/libsa/ufs.c @@ -0,0 +1,1027 @@ +/* $NetBSD: ufs.c,v 1.56 2011/12/25 06:09:08 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * Copyright (c) 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: David Golub + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * Stand-alone file reading package for UFS and LFS filesystems. + */ + +#include +#include +#include +#include +#ifdef LIBSA_LFS +#include +#include +#include /* XXX for MNAMELEN */ +#include +#else +#include +#endif +#ifdef _STANDALONE +#include +#else +#include +#endif + +#include "stand.h" +#ifdef LIBSA_LFS +#include "lfs.h" +#else +#include "ufs.h" +#endif + +/* If this file is compiled by itself, build ufs (aka ffsv1) support */ +#if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS) +#define LIBSA_FFSv1 +#endif + +#if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK) +#define LIBSA_NO_FS_SYMLINK +#endif +#if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS) +#undef COMPAT_UFS +#endif + +#ifdef LIBSA_LFS +/* + * In-core LFS superblock. This exists only to placate the macros in lfs.h, + */ +struct fs { + struct dlfs lfs_dlfs; +}; +#define fs_magic lfs_magic +#define fs_maxsymlinklen lfs_maxsymlinklen + +#define FS_MAGIC LFS_MAGIC +#define SBLOCKSIZE LFS_SBPAD +#define SBLOCKOFFSET LFS_LABELPAD +#else +/* NB ufs2 doesn't use the common suberblock code... */ +#define FS_MAGIC FS_UFS1_MAGIC +#define SBLOCKOFFSET SBLOCK_UFS1 +#endif + +#if defined(LIBSA_NO_TWIDDLE) +#define twiddle() +#endif + +#undef cgstart +#if defined(LIBSA_FFSv2) +#define cgstart(fc, c) cgstart_ufs2((fs), (c)) +#else +#define cgstart(fc, c) cgstart_ufs1((fs), (c)) +#endif + +#ifndef ufs_dinode +#define ufs_dinode ufs1_dinode +#endif +#ifndef indp_t +#define indp_t int32_t +#endif +typedef uint32_t ino32_t; +#ifndef FSBTODB +#define FSBTODB(fs, indp) fsbtodb(fs, indp) +#endif + +/* + * To avoid having a lot of filesystem-block sized buffers lurking (which + * could be 32k) we only keep a few entries of the indirect block map. + * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block + * ~13 times pulling in a 6M kernel. + * The cache size must be smaller than the smallest filesystem block, + * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks). + */ +#define LN2_IND_CACHE_SZ 6 +#define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ) +#define IND_CACHE_MASK (IND_CACHE_SZ - 1) + +/* + * In-core open file. + */ +struct file { + off_t f_seekp; /* seek pointer */ + struct fs *f_fs; /* pointer to super-block */ + struct ufs_dinode f_di; /* copy of on-disk inode */ + uint f_nishift; /* for blocks in indirect block */ + indp_t f_ind_cache_block; + indp_t f_ind_cache[IND_CACHE_SZ]; + + char *f_buf; /* buffer for data block */ + size_t f_buf_size; /* size of data block */ + daddr_t f_buf_blkno; /* block number of data block */ +}; + +static int read_inode(ino32_t, struct open_file *); +static int block_map(struct open_file *, indp_t, indp_t *); +static int buf_read_file(struct open_file *, char **, size_t *); +static int search_directory(const char *, int, struct open_file *, ino32_t *); +#ifdef LIBSA_FFSv1 +static void ffs_oldfscompat(struct fs *); +#endif +#ifdef LIBSA_FFSv2 +static int ffs_find_superblock(struct open_file *, struct fs *); +#endif + +#if defined(LIBSA_ENABLE_LS_OP) + +#define NELEM(x) (sizeof (x) / sizeof(*x)) + +typedef struct entry_t entry_t; +struct entry_t { + entry_t *e_next; + ino32_t e_ino; + uint8_t e_type; + char e_name[1]; +}; + +static const char *const typestr[] = { + "unknown", + "FIFO", + "CHR", + 0, + "DIR", + 0, + "BLK", + 0, + "REG", + 0, + "LNK", + 0, + "SOCK", + 0, + "WHT" +}; + +static int +fn_match(const char *fname, const char *pattern) +{ + char fc, pc; + + do { + fc = *fname++; + pc = *pattern++; + if (!fc && !pc) + return 1; + if (pc == '?' && fc) + pc = fc; + } while (fc == pc); + + if (pc != '*') + return 0; + /* + * Too hard (and unnecessary really) too check for "*?name" etc.... + * "**" will look for a '*' and "*?" a '?' + */ + pc = *pattern++; + if (!pc) + return 1; + while ((fname = strchr(fname, pc))) + if (fn_match(++fname, pattern)) + return 1; + return 0; +} +#endif /* LIBSA_ENABLE_LS_OP */ + +#ifdef LIBSA_LFS +/* + * Find an inode's block. Look it up in the ifile. Whee! + */ +static int +find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct fs *fs = fp->f_fs; + daddr_t ifileent_blkno; + char *ent_in_buf; + size_t buf_after_ent; + int rc; + + rc = read_inode(fs->lfs_ifile, f); + if (rc) + return rc; + + ifileent_blkno = + (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz; + fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize + + (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx); + rc = buf_read_file(f, &ent_in_buf, &buf_after_ent); + if (rc) + return rc; + /* make sure something's not badly wrong, but don't panic. */ + if (buf_after_ent < sizeof (IFILE_Vx)) + return EINVAL; + + *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr); + if (*isp == LFS_UNUSED_DADDR) /* again, something badly wrong */ + return EINVAL; + return 0; +} +#endif + +/* + * Read a new inode into a file structure. + */ +static int +read_inode(ino32_t inumber, struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct fs *fs = fp->f_fs; + char *buf; + size_t rsize; + int rc; + daddr_t inode_sector; +#ifdef LIBSA_LFS + struct ufs_dinode *dip; + int cnt; +#endif + +#ifdef LIBSA_LFS + if (inumber == fs->lfs_ifile) + inode_sector = FSBTODB(fs, fs->lfs_idaddr); + else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0) + return rc; +#else + inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber)); +#endif + + /* + * Read inode and save it. + */ + buf = fp->f_buf; + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + inode_sector, fs->fs_bsize, buf, &rsize); + if (rc) + return rc; + if (rsize != fs->fs_bsize) + return EIO; + +#ifdef LIBSA_LFS + cnt = INOPBx(fs); + dip = (struct ufs_dinode *)buf + (cnt - 1); + for (; dip->di_inumber != inumber; --dip) { + /* kernel code panics, but boot blocks which panic are Bad. */ + if (--cnt == 0) + return EINVAL; + } + fp->f_di = *dip; +#else + fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)]; +#endif + + /* + * Clear out the old buffers + */ + fp->f_ind_cache_block = ~0; + fp->f_buf_blkno = -1; + return rc; +} + +/* + * Given an offset in a file, find the disk block number that + * contains that block. + */ +static int +block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct fs *fs = fp->f_fs; + uint level; + indp_t ind_cache; + indp_t ind_block_num; + size_t rsize; + int rc; + indp_t *buf = (void *)fp->f_buf; + + /* + * Index structure of an inode: + * + * di_db[0..NDADDR-1] hold block numbers for blocks + * 0..NDADDR-1 + * + * di_ib[0] index block 0 is the single indirect block + * holds block numbers for blocks + * NDADDR .. NDADDR + NINDIR(fs)-1 + * + * di_ib[1] index block 1 is the double indirect block + * holds block numbers for INDEX blocks for blocks + * NDADDR + NINDIR(fs) .. + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 + * + * di_ib[2] index block 2 is the triple indirect block + * holds block numbers for double-indirect + * blocks for blocks + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. + * NDADDR + NINDIR(fs) + NINDIR(fs)**2 + * + NINDIR(fs)**3 - 1 + */ + + if (file_block < NDADDR) { + /* Direct block. */ + *disk_block_p = fp->f_di.di_db[file_block]; + return 0; + } + + file_block -= NDADDR; + + ind_cache = file_block >> LN2_IND_CACHE_SZ; + if (ind_cache == fp->f_ind_cache_block) { + *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK]; + return 0; + } + + for (level = 0;;) { + level += fp->f_nishift; + if (file_block < (indp_t)1 << level) + break; + if (level > NIADDR * fp->f_nishift) + /* Block number too high */ + return EFBIG; + file_block -= (indp_t)1 << level; + } + + ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1]; + + for (;;) { + level -= fp->f_nishift; + if (ind_block_num == 0) { + *disk_block_p = 0; /* missing */ + return 0; + } + + twiddle(); + /* + * If we were feeling brave, we could work out the number + * of the disk sector and read a single disk sector instead + * of a filesystem block. + * However we don't do this very often anyway... + */ + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize, + buf, &rsize); + if (rc) + return rc; + if (rsize != fs->fs_bsize) + return EIO; + ind_block_num = buf[file_block >> level]; + if (level == 0) + break; + file_block &= (1 << level) - 1; + } + + /* Save the part of the block that contains this sector */ + memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK], + IND_CACHE_SZ * sizeof fp->f_ind_cache[0]); + fp->f_ind_cache_block = ind_cache; + + *disk_block_p = ind_block_num; + + return 0; +} + +/* + * Read a portion of a file into an internal buffer. + * Return the location in the buffer and the amount in the buffer. + */ +static int +buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct fs *fs = fp->f_fs; + long off; + indp_t file_block; + indp_t disk_block; + size_t block_size; + int rc; + + off = blkoff(fs, fp->f_seekp); + file_block = lblkno(fs, fp->f_seekp); +#ifdef LIBSA_LFS + block_size = dblksize(fs, &fp->f_di, file_block); +#else + block_size = sblksize(fs, (int64_t)fp->f_di.di_size, file_block); +#endif + + if (file_block != fp->f_buf_blkno) { + rc = block_map(f, file_block, &disk_block); + if (rc) + return rc; + + if (disk_block == 0) { + memset(fp->f_buf, 0, block_size); + fp->f_buf_size = block_size; + } else { + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + FSBTODB(fs, disk_block), + block_size, fp->f_buf, &fp->f_buf_size); + if (rc) + return rc; + } + + fp->f_buf_blkno = file_block; + } + + /* + * Return address of byte in buffer corresponding to + * offset, and size of remainder of buffer after that + * byte. + */ + *buf_p = fp->f_buf + off; + *size_p = block_size - off; + + /* + * But truncate buffer at end of file. + */ + if (*size_p > fp->f_di.di_size - fp->f_seekp) + *size_p = fp->f_di.di_size - fp->f_seekp; + + return 0; +} + +/* + * Search a directory for a name and return its + * inode number. + */ +static int +search_directory(const char *name, int length, struct open_file *f, + ino32_t *inumber_p) +{ + struct file *fp = (struct file *)f->f_fsdata; + struct direct *dp; + struct direct *edp; + char *buf; + size_t buf_size; + int namlen; + int rc; + + fp->f_seekp = 0; + while (fp->f_seekp < (off_t)fp->f_di.di_size) { + rc = buf_read_file(f, &buf, &buf_size); + if (rc) + return rc; + + dp = (struct direct *)buf; + edp = (struct direct *)(buf + buf_size); + for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { + if (dp->d_reclen <= 0) + break; + if (dp->d_ino == (ino32_t)0) + continue; +#if BYTE_ORDER == LITTLE_ENDIAN + if (fp->f_fs->fs_maxsymlinklen <= 0) + namlen = dp->d_type; + else +#endif + namlen = dp->d_namlen; + if (namlen == length && + !memcmp(name, dp->d_name, length)) { + /* found entry */ + *inumber_p = dp->d_ino; + return 0; + } + } + fp->f_seekp += buf_size; + } + return ENOENT; +} + +#ifdef LIBSA_FFSv2 + +daddr_t sblock_try[] = SBLOCKSEARCH; + +static int +ffs_find_superblock(struct open_file *f, struct fs *fs) +{ + int i, rc; + size_t buf_size; + + for (i = 0; sblock_try[i] != -1; i++) { + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); + if (rc != 0 || buf_size != SBLOCKSIZE) + return rc; + if (fs->fs_sblockloc != sblock_try[i]) + /* an alternate superblock - try again */ + continue; + if (fs->fs_magic == FS_UFS2_MAGIC) { + return 0; + } + } + return EINVAL; +} + +#endif + +/* + * Open a file. + */ +__compactcall int +ufs_open(const char *path, struct open_file *f) +{ +#ifndef LIBSA_FS_SINGLECOMPONENT + const char *cp, *ncp; + int c; +#endif + ino32_t inumber; + struct file *fp; + struct fs *fs; + int rc; +#ifndef LIBSA_NO_FS_SYMLINK + ino32_t parent_inumber; + int nlinks = 0; + char namebuf[MAXPATHLEN+1]; + char *buf; +#endif + + /* allocate file system specific data structure */ + fp = alloc(sizeof(struct file)); + memset(fp, 0, sizeof(struct file)); + f->f_fsdata = (void *)fp; + + /* allocate space and read super block */ + fs = alloc(SBLOCKSIZE); + fp->f_fs = fs; + twiddle(); + +#ifdef LIBSA_FFSv2 + rc = ffs_find_superblock(f, fs); + if (rc) + goto out; +#else + { + size_t buf_size; + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); + if (rc) + goto out; + if (buf_size != SBLOCKSIZE || +#ifdef LIBSA_FFS + fs->lfs_version != REQUIRED_LFS_VERSION || +#endif + fs->fs_magic != FS_MAGIC) { + rc = EINVAL; + goto out; + } + } +#if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2 + /* + * XXX We should check the second superblock and use the eldest + * of the two. See comments near the top of lfs_mountfs() + * in sys/ufs/lfs/lfs_vfsops.c. + * This may need a LIBSA_LFS_SMALL check as well. + */ +#endif +#endif + +#ifdef LIBSA_FFSv1 + ffs_oldfscompat(fs); +#endif + + if (fs->fs_bsize > MAXBSIZE || + (size_t)fs->fs_bsize < sizeof(struct fs)) { + rc = EINVAL; + goto out; + } + + /* + * Calculate indirect block levels. + */ + { + indp_t mult; + int ln2; + + /* + * We note that the number of indirect blocks is always + * a power of 2. This lets us use shifts and masks instead + * of divide and remainder and avoinds pulling in the + * 64bit division routine into the boot code. + */ + mult = NINDIR(fs); +#ifdef DEBUG + if (mult & (mult - 1)) { + /* Hummm was't a power of 2 */ + rc = EINVAL; + goto out; + } +#endif + for (ln2 = 0; mult != 1; ln2++) + mult >>= 1; + + fp->f_nishift = ln2; + } + + /* alloc a block sized buffer used for all fs transfers */ + fp->f_buf = alloc(fs->fs_bsize); + inumber = ROOTINO; + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_FS_SINGLECOMPONENT + cp = path; + while (*cp) { + + /* + * Remove extra separators + */ + while (*cp == '/') + cp++; + if (*cp == '\0') + break; + + /* + * Check that current node is a directory. + */ + if ((fp->f_di.di_mode & IFMT) != IFDIR) { + rc = ENOTDIR; + goto out; + } + + /* + * Get next component of path name. + */ + ncp = cp; + while ((c = *cp) != '\0' && c != '/') + cp++; + + /* + * Look up component in current directory. + * Save directory inumber in case we find a + * symbolic link. + */ +#ifndef LIBSA_NO_FS_SYMLINK + parent_inumber = inumber; +#endif + rc = search_directory(ncp, cp - ncp, f, &inumber); + if (rc) + goto out; + + /* + * Open next component. + */ + if ((rc = read_inode(inumber, f)) != 0) + goto out; + +#ifndef LIBSA_NO_FS_SYMLINK + /* + * Check for symbolic link. + */ + if ((fp->f_di.di_mode & IFMT) == IFLNK) { + int link_len = fp->f_di.di_size; + int len; + + len = strlen(cp); + + if (link_len + len > MAXPATHLEN || + ++nlinks > MAXSYMLINKS) { + rc = ENOENT; + goto out; + } + + memmove(&namebuf[link_len], cp, len + 1); + + if (link_len < fs->fs_maxsymlinklen) { + memcpy(namebuf, fp->f_di.di_db, link_len); + } else { + /* + * Read file for symbolic link + */ + size_t buf_size; + indp_t disk_block; + + buf = fp->f_buf; + rc = block_map(f, (indp_t)0, &disk_block); + if (rc) + goto out; + + twiddle(); + rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, + F_READ, FSBTODB(fs, disk_block), + fs->fs_bsize, buf, &buf_size); + if (rc) + goto out; + + memcpy(namebuf, buf, link_len); + } + + /* + * If relative pathname, restart at parent directory. + * If absolute pathname, restart at root. + */ + cp = namebuf; + if (*cp != '/') + inumber = parent_inumber; + else + inumber = (ino32_t)ROOTINO; + + if ((rc = read_inode(inumber, f)) != 0) + goto out; + } +#endif /* !LIBSA_NO_FS_SYMLINK */ + } + + /* + * Found terminal component. + */ + rc = 0; + +#else /* !LIBSA_FS_SINGLECOMPONENT */ + + /* look up component in the current (root) directory */ + rc = search_directory(path, strlen(path), f, &inumber); + if (rc) + goto out; + + /* open it */ + rc = read_inode(inumber, f); + +#endif /* !LIBSA_FS_SINGLECOMPONENT */ + + fp->f_seekp = 0; /* reset seek pointer */ + +out: + if (rc) + ufs_close(f); + else { +#ifdef FSMOD + fsmod = FSMOD; +#endif +#ifdef FSMOD2 + fsmod2 = FSMOD2; +#endif + } + return rc; +} + +__compactcall int +ufs_close(struct open_file *f) +{ + struct file *fp = (struct file *)f->f_fsdata; + + f->f_fsdata = NULL; + if (fp == NULL) + return 0; + + if (fp->f_buf) + dealloc(fp->f_buf, fp->f_fs->fs_bsize); + dealloc(fp->f_fs, SBLOCKSIZE); + dealloc(fp, sizeof(struct file)); + return 0; +} + +/* + * Copy a portion of a file into kernel memory. + * Cross block boundaries when necessary. + */ +__compactcall int +ufs_read(struct open_file *f, void *start, size_t size, size_t *resid) +{ + struct file *fp = (struct file *)f->f_fsdata; + size_t csize; + char *buf; + size_t buf_size; + int rc = 0; + char *addr = start; + + while (size != 0) { + if (fp->f_seekp >= (off_t)fp->f_di.di_size) + break; + + rc = buf_read_file(f, &buf, &buf_size); + if (rc) + break; + + csize = size; + if (csize > buf_size) + csize = buf_size; + + memcpy(addr, buf, csize); + + fp->f_seekp += csize; + addr += csize; + size -= csize; + } + if (resid) + *resid = size; + return rc; +} + +/* + * Not implemented. + */ +#ifndef LIBSA_NO_FS_WRITE +__compactcall int +ufs_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !LIBSA_NO_FS_WRITE */ + +#ifndef LIBSA_NO_FS_SEEK +__compactcall off_t +ufs_seek(struct open_file *f, off_t offset, int where) +{ + struct file *fp = (struct file *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + fp->f_seekp = offset; + break; + case SEEK_CUR: + fp->f_seekp += offset; + break; + case SEEK_END: + fp->f_seekp = fp->f_di.di_size - offset; + break; + default: + return -1; + } + return fp->f_seekp; +} +#endif /* !LIBSA_NO_FS_SEEK */ + +__compactcall int +ufs_stat(struct open_file *f, struct stat *sb) +{ + struct file *fp = (struct file *)f->f_fsdata; + + /* only important stuff */ + memset(sb, 0, sizeof *sb); + sb->st_mode = fp->f_di.di_mode; + sb->st_uid = fp->f_di.di_uid; + sb->st_gid = fp->f_di.di_gid; + sb->st_size = fp->f_di.di_size; + return 0; +} + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +ufs_ls(struct open_file *f, const char *pattern) +{ + struct file *fp = (struct file *)f->f_fsdata; + char *buf; + size_t buf_size; + entry_t *names = 0, *n, **np; + + fp->f_seekp = 0; + while (fp->f_seekp < (off_t)fp->f_di.di_size) { + struct direct *dp, *edp; + int rc = buf_read_file(f, &buf, &buf_size); + if (rc) + goto out; + /* some firmware might use block size larger than DEV_BSIZE */ + if (buf_size < DIRBLKSIZ) + goto out; + + dp = (struct direct *)buf; + edp = (struct direct *)(buf + buf_size); + + for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) { + const char *t; + if (dp->d_ino == 0) + continue; + + if (dp->d_type >= NELEM(typestr) || + !(t = typestr[dp->d_type])) { + /* + * This does not handle "old" + * filesystems properly. On little + * endian machines, we get a bogus + * type name if the namlen matches a + * valid type identifier. We could + * check if we read namlen "0" and + * handle this case specially, if + * there were a pressing need... + */ + printf("bad dir entry\n"); + goto out; + } + if (pattern && !fn_match(dp->d_name, pattern)) + continue; + n = alloc(sizeof *n + strlen(dp->d_name)); + if (!n) { + printf("%d: %s (%s)\n", + dp->d_ino, dp->d_name, t); + continue; + } + n->e_ino = dp->d_ino; + n->e_type = dp->d_type; + strcpy(n->e_name, dp->d_name); + for (np = &names; *np; np = &(*np)->e_next) { + if (strcmp(n->e_name, (*np)->e_name) < 0) + break; + } + n->e_next = *np; + *np = n; + } + fp->f_seekp += buf_size; + } + + if (names) { + entry_t *p_names = names; + do { + n = p_names; + printf("%d: %s (%s)\n", + n->e_ino, n->e_name, typestr[n->e_type]); + p_names = n->e_next; + } while (p_names); + } else { + printf("not found\n"); + } +out: + if (names) { + do { + n = names; + names = n->e_next; + dealloc(n, 0); + } while (names); + } +} +#endif /* LIBSA_ENABLE_LS_OP */ + +#ifdef LIBSA_FFSv1 +/* + * Sanity checks for old file systems. + * + * XXX - goes away some day. + * Stripped of stuff libsa doesn't need..... + */ +static void +ffs_oldfscompat(struct fs *fs) +{ + +#ifdef COMPAT_UFS + /* + * Newer Solaris versions have a slightly incompatible + * superblock - so always calculate this values on the fly, which + * is good enough for libsa purposes + */ + if (fs->fs_magic == FS_UFS1_MAGIC +#ifndef COMPAT_SOLARIS_UFS + && fs->fs_old_inodefmt < FS_44INODEFMT +#endif + ) { + fs->fs_qbmask = ~fs->fs_bmask; + fs->fs_qfmask = ~fs->fs_fmask; + } +#endif +} +#endif diff --git a/sys/lib/libsa/ufs.h b/sys/lib/libsa/ufs.h new file mode 100644 index 000000000..2f93ea9ee --- /dev/null +++ b/sys/lib/libsa/ufs.h @@ -0,0 +1,36 @@ +/* $NetBSD: ufs.h,v 1.10 2011/12/25 06:09:08 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs.h 8.1 (Berkeley) 6/11/93 + */ + +FS_DEF(ufs); +FS_DEF(ffsv1); +FS_DEF(ffsv2); diff --git a/sys/lib/libsa/ustarfs.c b/sys/lib/libsa/ustarfs.c new file mode 100644 index 000000000..6dbe842f0 --- /dev/null +++ b/sys/lib/libsa/ustarfs.c @@ -0,0 +1,560 @@ +/* $NetBSD: ustarfs.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $ */ + +/* [Notice revision 2.2] + * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc. + * All rights reserved. + * + * Author: Ross Harvey + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright and + * author notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. This copyright will be assigned to The NetBSD Foundation on + * 1/1/2000 unless these terms (including possibly the assignment + * date) are updated in writing by Avalon prior to the latest specified + * assignment date. + * + * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/* + ******************************* USTAR FS ******************************* + */ + +/* + * Implement an ROFS with an 8K boot area followed by ustar-format data. + * The point: minimal FS overhead, and it's easy (well, `possible') to + * split files over multiple volumes. + * + * XXX - TODO LIST + * --- - ---- ---- + * XXX - tag volume numbers and verify that the correct volume is + * inserted after volume swaps. + * + * XXX - stop hardwiring FS metadata for floppies...embed it in a file, + * file name, or something. (Remember __SYMDEF? :-) + * + * XXX Does not currently implement: + * XXX + * XXX LIBSA_NO_FS_CLOSE + * XXX LIBSA_NO_FS_SEEK + * XXX LIBSA_NO_FS_WRITE + * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?) + * XXX LIBSA_FS_SINGLECOMPONENT + */ + +#ifdef _STANDALONE +#include +#else +#include +#endif +#include "stand.h" +#include "ustarfs.h" + +#define BBSIZE 8192 +#define USTAR_NAME_BLOCK 512 + +/* + * Virtual offset: relative to start of ustar archive + * Logical offset: volume-relative + * Physical offset: the usual meaning + */ + +/* virtual offset to volume number */ + +#define vda2vn(_v,_volsize) ((_v) / (_volsize)) + +/* conversions between the three different levels of disk addresses */ + +#define vda2lda(_v,_volsize) ((_v) % (_volsize)) +#define lda2vda(_v,_volsize,_volnumber) ((_v) + (_volsize) * (_volnumber)) + +#define lda2pda(_lda) ((_lda) + ustarfs_mode_offset) +#define pda2lda(_pda) ((_pda) - ustarfs_mode_offset) +/* + * Change this to off_t if you want to support big volumes. If we only use + * ustarfs on floppies it can stay int for libsa code density. + * + * It needs to be signed. + */ +typedef int ustoffs; + +typedef struct ustar_struct { + char ust_name[100], + ust_mode[8], + ust_uid[8], + ust_gid[8], + ust_size[12], + ust_misc[12 + 8 + 1 + 100], + ust_magic[6], + /* there is more, but we don't care */ + ust_pad[1]; /* make it aligned */ +} ustar_t; + +/* + * We buffer one even cylinder of data...it's actually only really one + * cyl on a 1.44M floppy, but on other devices it's fast enough with any + * kind of block buffering, so we optimize for the slowest device. + */ + +#ifndef USTAR_SECT_PER_CYL +#define USTAR_SECT_PER_CYL (18 * 2) +#endif + +typedef struct ust_active_struct { + ustar_t uas_active; + char uas_1cyl[USTAR_SECT_PER_CYL * 512]; + ustoffs uas_volsize; /* XXX this is hardwired now */ + ustoffs uas_windowbase; /* relative to volume 0 */ + ustoffs uas_filestart; /* relative to volume 0 */ + ustoffs uas_fseek; /* relative to file */ + ustoffs uas_filesize; /* relative to volume 0 */ + int uas_init_window; /* data present in window */ + int uas_init_fs; /* ust FS actually found */ + int uas_volzerosig; /* ID volume 0 by signature */ + int uas_sigdone; /* did sig already */ + int uas_offset; /* amount of cylinder below lba 0 */ +} ust_active_t; + +static const char formatid[] = "USTARFS", + metaname[] = "USTAR.volsize."; + +static const int ustarfs_mode_offset = BBSIZE; + +static int checksig(ust_active_t *); +static int convert(const char *, int, int); +static int get_volume(struct open_file *, int); +static void setwindow(ust_active_t *, ustoffs, ustoffs); +static int real_fs_cylinder_read(struct open_file *, ustoffs, int); +static int ustarfs_cylinder_read(struct open_file *, ustoffs, int); +static void ustarfs_sscanf(const char *, const char *, int *); +static int read512block(struct open_file *, ustoffs, char block[512]); +static int init_volzero_sig(struct open_file *); + +#ifdef HAVE_CHANGEDISK_HOOK +/* + * Called when the next volume is prompted. + * Machine dependent code can eject the medium etc. + * The new medium must be ready when this hook returns. + */ +void changedisk_hook(struct open_file *); +#endif + +static int +convert(const char *f, int base, int fw) +{ + int i, c, result = 0; + + while(fw > 0 && *f == ' ') { + --fw; + ++f; + } + for(i = 0; i < fw; ++i) { + c = f[i]; + if ('0' <= c && c < '0' + base) { + c -= '0'; + result = result * base + c; + } else break; + } + return result; +} + +static void +ustarfs_sscanf(const char *s, const char *f, int *xi) +{ + + *xi = convert(s, 8, convert(f + 1, 10, 99)); +} + +static int +ustarfs_cylinder_read(struct open_file *f, ustoffs seek2, int forcelabel) +{ + int i, e; + + for (i = 0; i < 3; ++i) { + e = real_fs_cylinder_read(f, seek2, forcelabel); + if (e == 0) + return 0; + } + return e; +} + +static int +real_fs_cylinder_read(struct open_file *f, ustoffs seek2, int forcelabel) +{ + int i; + int e = 0; /* XXX work around gcc warning */ + ustoffs lda; + char *xferbase; + ust_active_t *ustf; + size_t xferrqst, xfercount; + + ustf = f->f_fsdata; + xferrqst = sizeof ustf->uas_1cyl; + xferbase = ustf->uas_1cyl; + lda = pda2lda(seek2); + if (lda < 0) { + lda = -lda; + ustf->uas_offset = lda; + /* + * don't read the label unless we have to. (Preserve + * sequential block access so tape boot works.) + */ + if (!forcelabel) { + memset(xferbase, 0, lda); + xferrqst -= lda; + xferbase += lda; + seek2 += lda; + } + } else { + ustf->uas_offset = 0; + } + while(xferrqst > 0) { +#if !defined(LIBSA_NO_TWIDDLE) + twiddle(); +#endif + for (i = 0; i < 3; ++i) { + e = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, + seek2 / 512, xferrqst, xferbase, &xfercount); + if (e == 0) + break; + printf("@"); + } + if (e) + break; + if (xfercount != xferrqst) + printf("Warning, unexpected short transfer %d/%d\n", + (int)xfercount, (int)xferrqst); + xferrqst -= xfercount; + xferbase += xfercount; + seek2 += xfercount; + } + return e; +} + +static int +checksig(ust_active_t *ustf) +{ + int i, rcs; + + for(i = rcs = 0; i < (int)(sizeof ustf->uas_1cyl); ++i) + rcs += ustf->uas_1cyl[i]; + return rcs; +} + +static int +get_volume(struct open_file *f, int vn) +{ + int e, needvolume, havevolume; + ust_active_t *ustf; + + ustf = f->f_fsdata; + havevolume = vda2vn(ustf->uas_windowbase, ustf->uas_volsize); + needvolume = vn; + while(havevolume != needvolume) { + printf("\nPlease "); + if (havevolume >= 0) + printf("remove disk %d, ", havevolume + 1); + printf("insert disk %d, and press return...", + needvolume + 1); +#ifdef HAVE_CHANGEDISK_HOOK + changedisk_hook(f); +#else + for (;;) { + int c = getchar(); + if ((c == '\n') || (c == '\r')) + break; + } +#endif + printf("\n"); + e = ustarfs_cylinder_read(f, 0, needvolume != 0); + if (e) + return e; + if(strncmp(formatid, ustf->uas_1cyl, strlen(formatid))) { + /* no magic, might be OK if we want volume 0 */ + if (ustf->uas_volzerosig == checksig(ustf)) { + havevolume = 0; + continue; + } + printf("Disk is not from the volume set?!\n"); + havevolume = -2; + continue; + } + ustarfs_sscanf(ustf->uas_1cyl + strlen(formatid), "%9o", + &havevolume); + --havevolume; + } + return 0; +} + +static void +setwindow(ust_active_t *ustf, ustoffs pda, ustoffs vda) +{ + ustf->uas_windowbase = lda2vda(pda2lda(pda), ustf->uas_volsize, + vda2vn(vda, ustf->uas_volsize)) + + ustf->uas_offset; + ustf->uas_init_window = 1; +} + +static int +read512block(struct open_file *f, ustoffs vda, char block[512]) +{ + ustoffs pda; + ssize_t e; + int dienow; + ust_active_t *ustf; + + dienow = 0; + ustf = f->f_fsdata; + + /* + * if (vda in window) + * copy out and return data + * if (vda is on some other disk) + * do disk swap + * get physical disk address + * round down to cylinder boundary + * read cylinder + * set window (in vda space) and try again + * [ there is an implicit assumption that windowbase always identifies + * the current volume, even if initwindow == 0. This way, a + * windowbase of 0 causes the initial volume to be disk 0 ] + */ +tryagain: + if(ustf->uas_init_window + && ustf->uas_windowbase <= vda && vda < + ustf->uas_windowbase + + (int)(sizeof ustf->uas_1cyl) - ustf->uas_offset) { + memcpy(block, ustf->uas_1cyl + + (vda - ustf->uas_windowbase) + + ustf->uas_offset, 512); + return 0; + } + if (dienow++) + panic("ustarfs read512block"); + ustf->uas_init_window = 0; + e = get_volume(f, vda2vn(vda, ustf->uas_volsize)); + if (e) + return e; + pda = lda2pda(vda2lda(vda, ustf->uas_volsize)); + pda-= pda % sizeof ustf->uas_1cyl; + e = ustarfs_cylinder_read(f, pda, 0); + if (e) + return e; + setwindow(ustf, pda, vda); + goto tryagain; +} + +static int +init_volzero_sig(struct open_file *f) +{ + int e; + ust_active_t *ustf; + + ustf = f->f_fsdata; + if (!ustf->uas_sigdone) { + e = ustarfs_cylinder_read(f, 0, 0); + if (e) + return e; + ustf->uas_volzerosig = checksig(ustf); + setwindow(ustf, 0, 0); + } + return 0; +} + +__compactcall int +ustarfs_open(const char *path, struct open_file *f) +{ + ust_active_t *ustf; + ustoffs offset; + char block[512]; + int filesize; + int e, e2; + int newvolblocks; + + if (*path == '/') + ++path; + f->f_fsdata = ustf = alloc(sizeof *ustf); + memset(ustf, 0, sizeof *ustf); + offset = 0; + /* default to 2880 sector floppy */ + ustf->uas_volsize = 80 * 2 * 18 * 512 - lda2pda(0); + ustf->uas_fseek = 0; + e = init_volzero_sig(f); + if (e) + return e; + e2 = EINVAL; + for(;;) { + ustf->uas_filestart = offset; + e = read512block(f, offset, block); + if (e) + break; + memcpy(&ustf->uas_active, block, sizeof ustf->uas_active); + if(strncmp(ustf->uas_active.ust_magic, "ustar", 5)) { + e = e2; + break; + } + e2 = ENOENT; /* it must be an actual ustarfs */ + ustf->uas_init_fs = 1; + /* if volume metadata is found, use it */ + if(strncmp(ustf->uas_active.ust_name, metaname, + strlen(metaname)) == 0) { + ustarfs_sscanf(ustf->uas_active.ust_name + + strlen(metaname), "%99o", &newvolblocks); + ustf->uas_volsize = newvolblocks * 512 + - lda2pda(0); + } + ustarfs_sscanf(ustf->uas_active.ust_size,"%12o",&filesize); + if(strncmp(ustf->uas_active.ust_name, path, + sizeof ustf->uas_active.ust_name) == 0) { + ustf->uas_filesize = filesize; + break; + } + offset += USTAR_NAME_BLOCK + filesize; + filesize %= 512; + if (filesize) + offset += 512 - filesize; + } + if (e) { + dealloc(ustf, sizeof *ustf); + f->f_fsdata = 0; + } + return e; +} + +#ifndef LIBSA_NO_FS_WRITE +__compactcall int +ustarfs_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + + return EROFS; +} +#endif /* !LIBSA_NO_FS_WRITE */ + +#ifndef LIBSA_NO_FS_SEEK +__compactcall off_t +ustarfs_seek(struct open_file *f, off_t offs, int whence) +{ + ust_active_t *ustf; + + ustf = f->f_fsdata; + switch (whence) { + case SEEK_SET: + ustf->uas_fseek = offs; + break; + case SEEK_CUR: + ustf->uas_fseek += offs; + break; + case SEEK_END: + ustf->uas_fseek = ustf->uas_filesize - offs; + break; + default: + return -1; + } + return ustf->uas_fseek; +} +#endif /* !LIBSA_NO_FS_SEEK */ + +__compactcall int +ustarfs_read(struct open_file *f, void *start, size_t size, size_t *resid) +{ + ust_active_t *ustf; + int e; + char *space512; + int blkoffs; + int readoffs; + int bufferoffset; + size_t seg; + size_t infile; + size_t inbuffer; + + e = 0; + space512 = alloc(512); + ustf = f->f_fsdata; + while(size != 0) { + if (ustf->uas_fseek >= ustf->uas_filesize) + break; + bufferoffset = ustf->uas_fseek % 512; + blkoffs = ustf->uas_fseek - bufferoffset; + readoffs = ustf->uas_filestart + 512 + blkoffs; + e = read512block(f, readoffs, space512); + if (e) + break; + seg = size; + inbuffer = 512 - bufferoffset; + if (inbuffer < seg) + seg = inbuffer; + infile = ustf->uas_filesize - ustf->uas_fseek; + if (infile < seg) + seg = infile; + memcpy(start, space512 + bufferoffset, seg); + ustf->uas_fseek += seg; + start = (char *)start + seg; + size -= seg; + } + if (resid) + *resid = size; + dealloc(space512, 512); + return e; +} + +__compactcall int +ustarfs_stat(struct open_file *f, struct stat *sb) +{ + int mode, uid, gid; + ust_active_t *ustf; + + if (f == NULL) + return EINVAL; + ustf = f->f_fsdata; + memset(sb, 0, sizeof *sb); + ustarfs_sscanf(ustf->uas_active.ust_mode, "%8o", &mode); + ustarfs_sscanf(ustf->uas_active.ust_uid, "%8o", &uid); + ustarfs_sscanf(ustf->uas_active.ust_gid, "%8o", &gid); + sb->st_mode = mode; + sb->st_uid = uid; + sb->st_gid = gid; + sb->st_size = ustf->uas_filesize; + return 0; +} + + +#if defined(LIBSA_ENABLE_LS_OP) +__compactcall void +ustarfs_ls(struct open_file *f, const char *pattern) +{ + printf("Currently ls command is unsupported by ustarfs\n"); + return; +} +#endif + +#ifndef LIBSA_NO_FS_CLOSE +__compactcall int +ustarfs_close(struct open_file *f) +{ + if (f == NULL || f->f_fsdata == NULL) + return EINVAL; + dealloc(f->f_fsdata, sizeof(ust_active_t)); + f->f_fsdata = 0; + return 0; +} +#endif /* !LIBSA_NO_FS_CLOSE */ diff --git a/sys/lib/libsa/ustarfs.h b/sys/lib/libsa/ustarfs.h new file mode 100644 index 000000000..1a0e86f12 --- /dev/null +++ b/sys/lib/libsa/ustarfs.h @@ -0,0 +1,38 @@ +/* $NetBSD: ustarfs.h,v 1.3 2005/12/11 12:24:46 christos Exp $ */ + +/* [Notice revision 2.2] + * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc. + * All rights reserved. + * + * Author: Ross Harvey + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright and + * author notice, this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * 4. This copyright will be assigned to The NetBSD Foundation on + * 1/1/2000 unless these terms (including possibly the assignment + * date) are updated in writing by Avalon prior to the latest specified + * assignment date. + * + * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +FS_DEF(ustarfs); diff --git a/sys/lib/libsa/vsprintf.c b/sys/lib/libsa/vsprintf.c new file mode 100644 index 000000000..e7d3c4274 --- /dev/null +++ b/sys/lib/libsa/vsprintf.c @@ -0,0 +1,44 @@ +/* $NetBSD: vsprintf.c,v 1.5 2011/07/17 20:54:52 joerg Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)printf.c 8.1 (Berkeley) 6/11/93 + */ + +#include +#include + +#include "stand.h" + +int +vsprintf(char *buf, const char *fmt, va_list ap) +{ + + return vsnprintf(buf, -(size_t)buf, fmt, ap); +} diff --git a/sys/lib/libsa/write.c b/sys/lib/libsa/write.c new file mode 100644 index 000000000..a1e6e0f80 --- /dev/null +++ b/sys/lib/libsa/write.c @@ -0,0 +1,96 @@ +/* $NetBSD: write.c,v 1.15 2007/12/02 04:59:26 tsutsui Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * The Mach Operating System project at Carnegie-Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)write.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#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; +} diff --git a/tools/nbsd_ports b/tools/nbsd_ports index 251ba7ada..e4830d47f 100644 --- a/tools/nbsd_ports +++ b/tools/nbsd_ports @@ -42,3 +42,8 @@ usr.bin/bzip2recover src/usr.bin/bzip2recover libexec/makewhatis src/libexec/makewhatis dist/bzip2 src/dist/bzip2 share/zoneinfo src/share/zoneinfo +sys/arch/i386/stand/bootxx src/sys/arch/i386/stand/bootxx +sys/arch/i386/stand/boot src/sys/arch/i386/stand/boot +sys/arch/i386/stand/lib src/sys/arch/i386/stand/lib +sys/lib/libsa src/sys/lib/libsa +sys/lib/libz src/sys/lib/libz