18208Sjkh/*
28208Sjkh * The new sysinstall program.
38208Sjkh *
48208Sjkh * This is probably the last program in the `sysinstall' line - the next
58208Sjkh * generation being essentially a complete rewrite.
68208Sjkh *
750479Speter * $FreeBSD$
88208Sjkh *
98208Sjkh * Copyright (c) 1995
108208Sjkh *	Jordan Hubbard.  All rights reserved.
118208Sjkh *
128208Sjkh * Redistribution and use in source and binary forms, with or without
138208Sjkh * modification, are permitted provided that the following conditions
148208Sjkh * are met:
158208Sjkh * 1. Redistributions of source code must retain the above copyright
168881Srgrimes *    notice, this list of conditions and the following disclaimer,
178881Srgrimes *    verbatim and that no modifications are made prior to this
188208Sjkh *    point in the file.
198208Sjkh * 2. Redistributions in binary form must reproduce the above copyright
208208Sjkh *    notice, this list of conditions and the following disclaimer in the
218208Sjkh *    documentation and/or other materials provided with the distribution.
228208Sjkh *
238208Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
248208Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
258208Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
268208Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
278208Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
288208Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
298208Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
308208Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
318208Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
328208Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
338208Sjkh * SUCH DAMAGE.
348208Sjkh *
358208Sjkh */
368208Sjkh
378208Sjkh#include "sysinstall.h"
388441Sjkh#include <sys/fcntl.h>
398549Sjkh#include <sys/param.h>
408549Sjkh#include <sys/socket.h>
418549Sjkh#include <sys/ioctl.h>
4212781Sjkh#include <sys/errno.h>
4320484Sjkh#include <sys/time.h>
448549Sjkh#include <net/if.h>
4521373Sjkh#include <net/if_var.h>
468549Sjkh#include <net/if_dl.h>
478549Sjkh#include <netinet/in.h>
488549Sjkh#include <netinet/in_var.h>
498549Sjkh#include <arpa/inet.h>
508549Sjkh#include <ctype.h>
51133040Smarcel#include <libdisk.h>
528208Sjkh
538549Sjkhstatic Device *Devices[DEV_MAX];
548549Sjkhstatic int numDevs;
558363Sjkh
56156121Sjhb#define	DEVICE_ENTRY(type, name, descr, max)	{ type, name, descr, max }
57156121Sjhb
58156121Sjhb#define	CDROM(name, descr, max)					\
59156121Sjhb	DEVICE_ENTRY(DEVICE_TYPE_CDROM, name, descr, max)
60156121Sjhb#define	DISK(name, descr, max)						\
61156121Sjhb	DEVICE_ENTRY(DEVICE_TYPE_DISK, name, descr, max)
62156121Sjhb#define	FLOPPY(name, descr, max)					\
63156121Sjhb	DEVICE_ENTRY(DEVICE_TYPE_FLOPPY, name, descr, max)
64156121Sjhb#define	NETWORK(name, descr)						\
65156121Sjhb	DEVICE_ENTRY(DEVICE_TYPE_NETWORK, name, descr, 0)
66156121Sjhb#define	SERIAL(name, descr, max)					\
67156121Sjhb	DEVICE_ENTRY(DEVICE_TYPE_NETWORK, name, descr, max)
68194931Scperciva#define	USB(name, descr, max)						\
69194931Scperciva	DEVICE_ENTRY(DEVICE_TYPE_USB, name, descr, max)
70156121Sjhb
7133223Sjkhstatic struct _devname {
728549Sjkh    DeviceType type;
738549Sjkh    char *name;
748549Sjkh    char *description;
75156120Sjhb    int max;
768549Sjkh} device_names[] = {
77156121Sjhb    CDROM("cd%d",	"SCSI CDROM drive",			4),
78156121Sjhb    CDROM("mcd%d",	"Mitsumi (old model) CDROM drive",	4),
79156121Sjhb    CDROM("scd%d",	"Sony CDROM drive - CDU31/33A type",	4),
80156121Sjhb    CDROM("acd%d",	"ATAPI/IDE CDROM",			4),
81156121Sjhb    DISK("da%d",	"SCSI disk device",			16),
82156121Sjhb    DISK("ad%d",	"ATA/IDE disk device",			16),
83196213Scperciva    DISK("ada%d",	"SATA disk device",			16),
84156121Sjhb    DISK("ar%d",	"ATA/IDE RAID device",			16),
85156121Sjhb    DISK("afd%d",	"ATAPI/IDE floppy device",		4),
86156121Sjhb    DISK("mlxd%d",	"Mylex RAID disk",			4),
87156121Sjhb    DISK("amrd%d",	"AMI MegaRAID drive",			4),
88156121Sjhb    DISK("idad%d",	"Compaq RAID array",			4),
89156121Sjhb    DISK("twed%d",	"3ware ATA RAID array",			4),
90156121Sjhb    DISK("aacd%d",	"Adaptec FSA RAID array",		4),
91156121Sjhb    DISK("ipsd%d",	"IBM ServeRAID RAID array",		4),
92157260Sscottl    DISK("mfid%d",	"LSI MegaRAID SAS array",		4),
93156121Sjhb    FLOPPY("fd%d",	"floppy drive unit A",			4),
94216052Sbrucec    SERIAL("cuau%d",	"%s on device %s (COM%d)",		16),
95194931Scperciva    USB("da%da",	"USB Mass Storage Device",		16),
96186965Sbrueffer    NETWORK("ae",	"Attansic/Atheros L2 Fast Ethernet"),
97179107Syongari    NETWORK("age",	"Attansic/Atheros L1 Gigabit Ethernet"),
98193883Syongari    NETWORK("alc",	"Atheros AR8131/AR8132 PCIe Ethernet"),
99184871Syongari    NETWORK("ale",	"Atheros AR8121/AR8113/AR8114 PCIe Ethernet"),
100156121Sjhb    NETWORK("an",	"Aironet 4500/4800 802.11 wireless adapter"),
101161494Sbrueffer    NETWORK("ath",	"Atheros IEEE 802.11 wireless adapter"),
102167634Sbrueffer    NETWORK("aue",	"ADMtek USB Ethernet adapter"),
103167634Sbrueffer    NETWORK("axe",	"ASIX Electronics USB Ethernet adapter"),
104161494Sbrueffer    NETWORK("bce",	"Broadcom NetXtreme II Gigabit Ethernet card"),
105167634Sbrueffer    NETWORK("bfe",	"Broadcom BCM440x PCI Ethernet card"),
106167634Sbrueffer    NETWORK("bge",	"Broadcom BCM570x PCI Gigabit Ethernet card"),
107191392Snwhitehorn    NETWORK("bm",	"Apple BMAC Built-in Ethernet"),
108204328Sweongyo    NETWORK("bwn",	"Broadcom BCM43xx IEEE 802.11 wireless adapter"),
109219647Sdavidch    NETWORK("bxe",	"Broadcom NetXtreme II 10Gb Ethernet card"),
110194249Smarius    NETWORK("cas",	"Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"),
111167634Sbrueffer    NETWORK("cue",	"CATC USB Ethernet adapter"),
112167634Sbrueffer    NETWORK("cxgb",	"Chelsio T3 10Gb Ethernet card"),
113218792Snp    NETWORK("cxgbe",	"Chelsio T4 10Gb Ethernet card"),
114156121Sjhb    NETWORK("fpa",	"DEC DEFPA PCI FDDI card"),
115156121Sjhb    NETWORK("sr",	"SDL T1/E1 sync serial PCI card"),
116156121Sjhb    NETWORK("cc3i",	"SDL HSSI sync serial PCI card"),
117156121Sjhb    NETWORK("en",	"Efficient Networks ATM PCI card"),
118167634Sbrueffer    NETWORK("dc",	"DEC/Intel 21143 (and clones) PCI Fast Ethernet card"),
119156121Sjhb    NETWORK("de",	"DEC DE435 PCI NIC or other DC21040-AA based card"),
120156121Sjhb    NETWORK("fxp",	"Intel EtherExpress Pro/100B PCI Fast Ethernet card"),
121156121Sjhb    NETWORK("ed",	"Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"),
122167705Sbrueffer    NETWORK("ep",	"3Com 3C509 Ethernet card/3C589 PCMCIA"),
123167634Sbrueffer    NETWORK("em",	"Intel(R) PRO/1000 Ethernet card"),
124186965Sbrueffer    NETWORK("et",	"Agere ET1310 based PCI Express Gigabit Ethernet card"),
125167634Sbrueffer    NETWORK("ex",	"Intel EtherExpress Pro/10 Ethernet card"),
126167634Sbrueffer    NETWORK("fe",	"Fujitsu MB86960A/MB86965A Ethernet card"),
127167634Sbrueffer    NETWORK("gem",	"Apple GMAC or Sun ERI/GEM Ethernet adapter"),
128167634Sbrueffer    NETWORK("hme",	"Sun HME (Happy Meal Ethernet) Ethernet adapter"),
129156121Sjhb    NETWORK("ie",	"AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"),
130186965Sbrueffer    NETWORK("igb",	"Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"),
131177990Sweongyo    NETWORK("ipw",	"Intel PRO/Wireless 2100 IEEE 802.11 adapter"),
132177990Sweongyo    NETWORK("iwi",	"Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"),
133186965Sbrueffer    NETWORK("iwn",	"Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"),
134161494Sbrueffer    NETWORK("ixgb",	"Intel(R) PRO/10Gb Ethernet card"),
135186965Sbrueffer    NETWORK("ixgbe",	"Intel(R) PRO/10Gb Ethernet card"),
136179344Syongari    NETWORK("jme",	"JMicron JMC250 Gigabit/JMC260 Fast Ethernet"),
137167634Sbrueffer    NETWORK("kue",	"Kawasaki LSI USB Ethernet adapter"),
138167634Sbrueffer    NETWORK("le",	"AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"),
139167634Sbrueffer    NETWORK("lge",	"Level 1 LXT1001 Gigabit Ethernet card"),
140177990Sweongyo    NETWORK("malo",	"Marvell Libertas 88W8335 802.11 wireless adapter"),
141167634Sbrueffer    NETWORK("msk",	"Marvell/SysKonnect Yukon II Gigabit Ethernet"),
142161494Sbrueffer    NETWORK("mxge",	"Myricom Myri10GE 10Gb Ethernet card"),
143161494Sbrueffer    NETWORK("nfe",	"NVIDIA nForce MCP Ethernet"),
144167634Sbrueffer    NETWORK("nge",	"NatSemi PCI Gigabit Ethernet card"),
145161494Sbrueffer    NETWORK("nve",	"NVIDIA nForce MCP Ethernet"),
146186965Sbrueffer    NETWORK("nxge",	"Neterion Xframe 10GbE Server/Storage adapter"),
147167634Sbrueffer    NETWORK("pcn",	"AMD Am79c79x PCI Ethernet card"),
148177990Sweongyo    NETWORK("ral",	"Ralink Technology IEEE 802.11 wireless adapter"),
149167634Sbrueffer    NETWORK("ray",	"Raytheon Raylink 802.11 wireless adapter"),
150167634Sbrueffer    NETWORK("re",	"RealTek 8139C+/8169/8169S/8110S PCI Ethernet card"),
151167634Sbrueffer    NETWORK("rl",	"RealTek 8129/8139 PCI Ethernet card"),
152167634Sbrueffer    NETWORK("rue",	"RealTek USB Ethernet card"),
153177990Sweongyo    NETWORK("rum",	"Ralink Technology USB IEEE 802.11 wireless adapter"),
154167634Sbrueffer    NETWORK("sf",	"Adaptec AIC-6915 PCI Ethernet card"),
155206628Syongari    NETWORK("sge",	"Silicon Integrated Systems SiS190/191 Ethernet"),
156167634Sbrueffer    NETWORK("sis",	"SiS 900/SiS 7016 PCI Ethernet card"),
15769791Snyan#ifdef PC98
158167634Sbrueffer    NETWORK("snc",	"SONIC Ethernet card"),
15969791Snyan#endif
160167634Sbrueffer    NETWORK("sn",	"SMC/Megahertz Ethernet card"),
161167634Sbrueffer    NETWORK("ste",	"Sundance ST201 PCI Ethernet card"),
162167634Sbrueffer    NETWORK("stge",	"Sundance/Tamarack TC9021 Gigabit Ethernet"),
163167634Sbrueffer    NETWORK("sk",	"SysKonnect PCI Gigabit Ethernet card"),
164167634Sbrueffer    NETWORK("tx",	"SMC 9432TX Ethernet card"),
165167634Sbrueffer    NETWORK("txp",	"3Com 3cR990 Ethernet card"),
166167634Sbrueffer    NETWORK("ti",	"Alteon Networks PCI Gigabit Ethernet card"),
167167634Sbrueffer    NETWORK("tl",	"Texas Instruments ThunderLAN PCI Ethernet card"),
168190790Sweongyo    NETWORK("uath",	"Atheros AR5005UG and AR5005UX USB wireless adapter"),
169181582Sweongyo    NETWORK("upgt",	"Conexant/Intersil PrismGT USB wireless adapter"),
170177990Sweongyo    NETWORK("ural",	"Ralink Technology RT2500USB 802.11 wireless adapter"),
171187615Sweongyo    NETWORK("urtw",	"Realtek 8187L USB wireless adapter"),
172167634Sbrueffer    NETWORK("vge",	"VIA VT612x PCI Gigabit Ethernet card"),
173167634Sbrueffer    NETWORK("vr",	"VIA VT3043/VT86C100A Rhine PCI Ethernet card"),
174216830Syongari    NETWORK("vte",	"DM&P Vortex86 RDC R6040 Fast Ethernet"),
175156121Sjhb    NETWORK("vlan",	"IEEE 802.1Q VLAN network interface"),
176167634Sbrueffer    NETWORK("vx",	"3COM 3c590 / 3c595 Ethernet card"),
177167634Sbrueffer    NETWORK("wb",	"Winbond W89C840F PCI Ethernet card"),
178156121Sjhb    NETWORK("wi",	"Lucent WaveLAN/IEEE 802.11 wireless adapter"),
179177990Sweongyo    NETWORK("wpi",	"Intel 3945ABG IEEE 802.11 wireless adapter"),
180167634Sbrueffer    NETWORK("xe",	"Xircom/Intel EtherExpress Pro100/16 Ethernet card"),
181167634Sbrueffer    NETWORK("xl",	"3COM 3c90x / 3c90xB PCI Ethernet card"),
182177990Sweongyo    NETWORK("zyd",	"ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"),
183156121Sjhb    NETWORK("fwe",	"FireWire Ethernet emulation"),
184161494Sbrueffer    NETWORK("fwip",	"IP over FireWire"),
185156121Sjhb    NETWORK("plip",	"Parallel Port IP (PLIP) peer connection"),
186156121Sjhb    NETWORK("lo",	"Loop-back (local) network interface"),
187156121Sjhb    NETWORK("disc",	"Software discard network interface"),
188156121Sjhb    { 0, NULL, NULL, 0 }
1898549Sjkh};
1908262Sjkh
1918641SjkhDevice *
1928549Sjkhnew_device(char *name)
1938208Sjkh{
1948549Sjkh    Device *dev;
1958549Sjkh
1968549Sjkh    dev = safe_malloc(sizeof(Device));
1979202Srgrimes    bzero(dev, sizeof(Device));
1988549Sjkh    if (name)
19920247Sjkh	SAFE_STRCPY(dev->name, name);
2008549Sjkh    return dev;
2018262Sjkh}
2028208Sjkh
2039202Srgrimes/* Stubs for unimplemented strategy routines */
2049202SrgrimesBoolean
2059202SrgrimesdummyInit(Device *dev)
2069202Srgrimes{
2079202Srgrimes    return TRUE;
2089202Srgrimes}
2099202Srgrimes
21020315SjkhFILE *
21114321SjkhdummyGet(Device *dev, char *dist, Boolean probe)
2129202Srgrimes{
21320315Sjkh    return NULL;
2149202Srgrimes}
2159202Srgrimes
2169202Srgrimesvoid
2179202SrgrimesdummyShutdown(Device *dev)
2189202Srgrimes{
2199202Srgrimes    return;
2209202Srgrimes}
2219202Srgrimes
2228549Sjkhstatic int
22333223SjkhdeviceTry(struct _devname dev, char *try, int i)
2248262Sjkh{
2258556Sjkh    int fd;
22633223Sjkh    char unit[80];
2278262Sjkh
22833223Sjkh    snprintf(unit, sizeof unit, dev.name, i);
22933223Sjkh    snprintf(try, FILENAME_MAX, "/dev/%s", unit);
23057490Sjkh    if (isDebug())
23157490Sjkh	msgDebug("deviceTry: attempting to open %s\n", try);
23234625Sjkh    fd = open(try, O_RDONLY);
23357490Sjkh    if (fd >= 0) {
23457490Sjkh	if (isDebug())
23557490Sjkh	    msgDebug("deviceTry: open of %s succeeded on first try.\n", try);
236155424Sceri    } else {
23757490Sjkh	if (isDebug())
238155424Sceri	    msgDebug("deviceTry: open of %s failed.\n", try);
23957490Sjkh    }
2408549Sjkh    return fd;
2418208Sjkh}
2428208Sjkh
2438641Sjkh/* Register a new device in the devices array */
2448641SjkhDevice *
2458641SjkhdeviceRegister(char *name, char *desc, char *devname, DeviceType type, Boolean enabled,
24620315Sjkh	       Boolean (*init)(Device *), FILE * (*get)(Device *, char *, Boolean),
24720315Sjkh	       void (*shutdown)(Device *), void *private)
2488641Sjkh{
24916348Sjkh    Device *newdev = NULL;
2508641Sjkh
2518641Sjkh    if (numDevs == DEV_MAX)
2528641Sjkh	msgFatal("Too many devices found!");
25316330Sjkh    else {
25416330Sjkh	newdev = new_device(name);
25516330Sjkh	newdev->description = desc;
25616330Sjkh	newdev->devname = devname;
25716330Sjkh	newdev->type = type;
25816330Sjkh	newdev->enabled = enabled;
25916330Sjkh	newdev->init = init ? init : dummyInit;
26016330Sjkh	newdev->get = get ? get : dummyGet;
26116330Sjkh	newdev->shutdown = shutdown ? shutdown : dummyShutdown;
26216330Sjkh	newdev->private = private;
26316330Sjkh	Devices[numDevs] = newdev;
26416330Sjkh	Devices[++numDevs] = NULL;
26516330Sjkh    }
2668641Sjkh    return newdev;
2678641Sjkh}
2688722Sjkh
26945371Sjkh/* Reset the registered device chain */
27045371Sjkhvoid
27145371SjkhdeviceReset(void)
27245371Sjkh{
27345371Sjkh    int i;
27445371Sjkh
27545371Sjkh    for (i = 0; i < numDevs; i++) {
27679065Sdd	DEVICE_SHUTDOWN(Devices[i]);
27745371Sjkh
27845371Sjkh	/* XXX this potentially leaks Devices[i]->private if it's being
27945371Sjkh	 * used to point to something dynamic, but you're not supposed
28045371Sjkh	 * to call this routine at such times that some open instance
28145371Sjkh	 * has its private ptr pointing somewhere anyway. XXX
28245371Sjkh	 */
28345371Sjkh	free(Devices[i]);
28445371Sjkh    }
28545371Sjkh    Devices[numDevs = 0] = NULL;
28645371Sjkh}
28745371Sjkh
2888549Sjkh/* Get all device information for devices we have attached */
2898549Sjkhvoid
2908556SjkhdeviceGetAll(void)
2918208Sjkh{
29233223Sjkh    int i, j, fd, s;
2938549Sjkh    struct ifconf ifc;
2948549Sjkh    struct ifreq *ifptr, *end;
2958556Sjkh    int ifflags;
2968556Sjkh    char buffer[INTERFACE_MAX * sizeof(struct ifreq)];
2978556Sjkh    char **names;
2988208Sjkh
29939800Sdanny    msgNotify("Probing devices, please wait (this can take a while)...");
30033223Sjkh    /* First go for the network interfaces.  Stolen shamelessly from ifconfig! */
301209235Sbrucec    memset(&ifc, 0, sizeof(ifc));
302209235Sbrucec    memset(buffer, 0, INTERFACE_MAX * sizeof(struct ifreq));
30318704Sjkh    ifc.ifc_len = sizeof(buffer);
30418704Sjkh    ifc.ifc_buf = buffer;
30518704Sjkh
30618704Sjkh    s = socket(AF_INET, SOCK_DGRAM, 0);
30747542Sjkh    if (s < 0)
30820208Sjkh	goto skipif;	/* Jump over network iface probing */
30947542Sjkh
31047542Sjkh    if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0)
31120208Sjkh	goto skipif;	/* Jump over network iface probing */
31247542Sjkh
31384152Smurray    close(s);
31418704Sjkh    ifflags = ifc.ifc_req->ifr_flags;
31518704Sjkh    end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
31618704Sjkh    for (ifptr = ifc.ifc_req; ifptr < end; ifptr++) {
31718704Sjkh	char *descr;
31818704Sjkh
31918704Sjkh	/* If it's not a link entry, forget it */
32018704Sjkh	if (ifptr->ifr_ifru.ifru_addr.sa_family != AF_LINK)
32147983Smarkm	    goto loopend;
32220208Sjkh
32318704Sjkh	/* Eliminate network devices that don't make sense */
32433223Sjkh	if (!strncmp(ifptr->ifr_name, "lo", 2))
32547983Smarkm	    goto loopend;
32620208Sjkh
32720208Sjkh	/* Try and find its description */
32820208Sjkh	for (i = 0, descr = NULL; device_names[i].name; i++) {
32918704Sjkh	    int len = strlen(device_names[i].name);
33018704Sjkh
33133223Sjkh	    if (!ifptr->ifr_name || !ifptr->ifr_name[0])
33233223Sjkh		continue;
33333223Sjkh	    else if (!strncmp(ifptr->ifr_name, device_names[i].name, len)) {
33418704Sjkh		descr = device_names[i].description;
33518704Sjkh		break;
33618704Sjkh	    }
33718704Sjkh	}
33818704Sjkh	if (!descr)
33918704Sjkh	    descr = "<unknown network interface type>";
34020208Sjkh
34118704Sjkh	deviceRegister(ifptr->ifr_name, descr, strdup(ifptr->ifr_name), DEVICE_TYPE_NETWORK, TRUE,
34220315Sjkh		       mediaInitNetwork, NULL, mediaShutdownNetwork, NULL);
34357490Sjkh	if (isDebug())
34457490Sjkh	    msgDebug("Found a network device named %s\n", ifptr->ifr_name);
34518704Sjkh	close(s);
34647542Sjkh	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
34718704Sjkh	    continue;
34847542Sjkh
34947983Smarkmloopend:
35018704Sjkh	if (ifptr->ifr_addr.sa_len)	/* I'm not sure why this is here - it's inherited */
35118704Sjkh	    ifptr = (struct ifreq *)((caddr_t)ifptr + ifptr->ifr_addr.sa_len - sizeof(struct sockaddr));
35284152Smurray	close(s);
35318704Sjkh    }
35418704Sjkh
35520208Sjkhskipif:
35633223Sjkh    /* Next, try to find all the types of devices one might need
35718704Sjkh     * during the second stage of the installation.
3588549Sjkh     */
3598549Sjkh    for (i = 0; device_names[i].name; i++) {
36033223Sjkh	for (j = 0; j < device_names[i].max; j++) {
36133223Sjkh	    char try[FILENAME_MAX];
3628636Sjkh
36333223Sjkh	    switch(device_names[i].type) {
36433223Sjkh	    case DEVICE_TYPE_CDROM:
36533223Sjkh		fd = deviceTry(device_names[i], try, j);
36633223Sjkh		if (fd >= 0 || errno == EBUSY) {	/* EBUSY if already mounted */
36733224Sjkh		    char n[BUFSIZ];
36833224Sjkh
36933223Sjkh		    if (fd >= 0) close(fd);
37033224Sjkh		    snprintf(n, sizeof n, device_names[i].name, j);
371209235Sbrucec		    deviceRegister(n, device_names[i].description, strdup(try),
37233223Sjkh					 DEVICE_TYPE_CDROM, TRUE, mediaInitCDROM, mediaGetCDROM,
37333223Sjkh					 mediaShutdownCDROM, NULL);
37457490Sjkh		    if (isDebug())
37557490Sjkh			msgDebug("Found a CDROM device for %s\n", try);
37633223Sjkh		}
37733223Sjkh		break;
3788262Sjkh
37933223Sjkh	    case DEVICE_TYPE_DISK:
380155424Sceri		/* nothing to do */
38133223Sjkh		break;
38233223Sjkh
38333223Sjkh	    case DEVICE_TYPE_FLOPPY:
38433223Sjkh		fd = deviceTry(device_names[i], try, j);
38533223Sjkh		if (fd >= 0) {
38633224Sjkh		    char n[BUFSIZ];
38733224Sjkh
38833223Sjkh		    close(fd);
38933224Sjkh		    snprintf(n, sizeof n, device_names[i].name, j);
390209235Sbrucec		    deviceRegister(n, device_names[i].description, strdup(try),
39133223Sjkh				   DEVICE_TYPE_FLOPPY, TRUE, mediaInitFloppy, mediaGetFloppy,
39233223Sjkh				   mediaShutdownFloppy, NULL);
39357490Sjkh		    if (isDebug())
39457490Sjkh			msgDebug("Found a floppy device for %s\n", try);
39533223Sjkh		}
39633223Sjkh		break;
39733223Sjkh
398194931Scperciva	    case DEVICE_TYPE_USB:
399194931Scperciva		fd = deviceTry(device_names[i], try, j);
400194931Scperciva		if (fd >= 0) {
401194931Scperciva			char n[BUFSIZ];
402194931Scperciva
403194931Scperciva			close(fd);
404194931Scperciva			snprintf(n, sizeof(n), device_names[i].name, j);
405209235Sbrucec			deviceRegister(n, device_names[i].description,
406194931Scperciva			    strdup(try), DEVICE_TYPE_USB, TRUE, mediaInitUSB,
407194931Scperciva			    mediaGetUSB, mediaShutdownUSB, NULL);
408194931Scperciva
409194931Scperciva			if (isDebug())
410194931Scperciva				msgDebug("Found a USB disk for %s\n", try);
411194931Scperciva		}
412194931Scperciva		break;
413194931Scperciva
41433223Sjkh	    default:
41533223Sjkh		break;
4168576Sjkh	    }
41733223Sjkh	}
41833223Sjkh    }
4198576Sjkh
420194807Scperciva    /* Finally, go get the disks and look for partitions to register */
42133223Sjkh    if ((names = Disk_Names()) != NULL) {
42233223Sjkh	int i;
42316348Sjkh
42433223Sjkh	for (i = 0; names[i]; i++) {
42533223Sjkh	    Chunk *c1;
42633223Sjkh	    Disk *d;
42733223Sjkh
42862620Sjkh	    /* Ignore memory disks */
429111918Ssobomax	    if (!strncmp(names[i], "md", 2))
43062577Sphk		continue;
43162620Sjkh
432139168Syongari	    /*
433139168Syongari	     * XXX
434139168Syongari	     *  Due to unknown reasons, Disk_Names() returns SCSI CDROM as a
435139168Syongari	     * valid disk. This is main reason why sysinstall presents SCSI
436139168Syongari	     * CDROM to available disks in Fdisk/Label menu. In addition,
437139168Syongari	     * adding a blank SCSI CDROM to the menu generates floating point
438139168Syongari	     * exception in sparc64. Disk_Names() just extracts sysctl
439139168Syongari	     * "kern.disks". Why GEOM treats SCSI CDROM as a disk is beyond
440139168Syongari	     * me and that should be investigated.
441139168Syongari	     * For temporary workaround, ignore SCSI CDROM device.
442139168Syongari	     */
443139168Syongari	    if (!strncmp(names[i], "cd", 2))
444139168Syongari		continue;
445139168Syongari
44633223Sjkh	    d = Open_Disk(names[i]);
44762577Sphk	    if (!d) {
448106279Skuriyama		msgDebug("Unable to open disk %s\n", names[i]);
44962577Sphk		continue;
45062577Sphk	    }
45133223Sjkh
45233223Sjkh	    deviceRegister(names[i], names[i], d->name, DEVICE_TYPE_DISK, FALSE,
45333223Sjkh			   dummyInit, dummyGet, dummyShutdown, d);
45457490Sjkh	    if (isDebug())
45557490Sjkh		msgDebug("Found a disk device named %s\n", names[i]);
45633223Sjkh
457194807Scperciva	    /* Look for existing DOS partitions to register as "DOS media devices"
458194807Scperciva	     * XXX: libdisks handling of extended partitions is too
459194807Scperciva	     * simplistic - it does not handle them containing (for
460194807Scperciva	     * example) UFS partitions
461194807Scperciva	     */
46233223Sjkh	    for (c1 = d->chunks->part; c1; c1 = c1->next) {
463106839Smarcel		if (c1->type == fat || c1->type == efi || c1->type == extended) {
46433223Sjkh		    Device *dev;
46533223Sjkh		    char devname[80];
46633223Sjkh
46733223Sjkh		    /* Got one! */
46833223Sjkh		    snprintf(devname, sizeof devname, "/dev/%s", c1->name);
46933223Sjkh		    dev = deviceRegister(c1->name, c1->name, strdup(devname), DEVICE_TYPE_DOS, TRUE,
47033223Sjkh					 mediaInitDOS, mediaGetDOS, mediaShutdownDOS, NULL);
47133223Sjkh		    dev->private = c1;
47257490Sjkh		    if (isDebug())
473194807Scperciva			msgDebug("Found a DOS partition %s\n", c1->name);
474194807Scperciva		} else if (c1->type == freebsd) {
475194807Scperciva		    Device *dev;
476194807Scperciva		    char devname[80];
477194807Scperciva		    Chunk *c2;
478194807Scperciva
479194807Scperciva		    for (c2 = c1->part; c2; c2 = c2->next) {
480194807Scperciva			if (c2->type != part || c2->subtype != 7)
481194807Scperciva			    continue;
482194807Scperciva			/* Got one! */
483194807Scperciva			snprintf(devname, sizeof devname, "/dev/%s", c1->name);
484194807Scperciva			dev = deviceRegister(c2->name, c2->name, strdup(devname), DEVICE_TYPE_UFS, TRUE,
485194807Scperciva					     mediaInitUFS, mediaGetUFS, mediaShutdownUFS, NULL);
486194807Scperciva			dev->private = c2;
487194807Scperciva			if (isDebug())
488194807Scperciva			    msgDebug("Found a UFS sub-partition %s\n", c2->name);
489194807Scperciva		    }
49033223Sjkh		}
491194807Scperciva
4928623Sjkh	    }
4938549Sjkh	}
49433223Sjkh	free(names);
4958549Sjkh    }
49654722Sjkh    dialog_clear_norefresh();
4978549Sjkh}
4988281Sjkh
49945371Sjkh/* Rescan all devices, after closing previous set - convenience function */
50045371Sjkhvoid
50145371SjkhdeviceRescan(void)
50245371Sjkh{
50345371Sjkh    deviceReset();
50445371Sjkh    deviceGetAll();
50545371Sjkh}
50645371Sjkh
5078549Sjkh/*
5088549Sjkh * Find all devices that match the criteria, allowing "wildcarding" as well
5098641Sjkh * by allowing NULL or ANY values to match all.  The array returned is static
5108641Sjkh * and may be used until the next invocation of deviceFind().
5118549Sjkh */
5128549SjkhDevice **
5138549SjkhdeviceFind(char *name, DeviceType class)
5148549Sjkh{
5158549Sjkh    static Device *found[DEV_MAX];
5168549Sjkh    int i, j;
5178307Sjkh
51821276Sjkh    j = 0;
51921276Sjkh    for (i = 0; i < numDevs; i++) {
5208576Sjkh	if ((!name || !strcmp(Devices[i]->name, name))
5218576Sjkh	    && (class == DEVICE_TYPE_ANY || class == Devices[i]->type))
5228549Sjkh	    found[j++] = Devices[i];
5238208Sjkh    }
5248549Sjkh    found[j] = NULL;
5258549Sjkh    return j ? found : NULL;
5268208Sjkh}
5278262Sjkh
52821730SjkhDevice **
52921730SjkhdeviceFindDescr(char *name, char *desc, DeviceType class)
53021730Sjkh{
53121730Sjkh    static Device *found[DEV_MAX];
53221730Sjkh    int i, j;
53321730Sjkh
53421730Sjkh    j = 0;
53521730Sjkh    for (i = 0; i < numDevs; i++) {
53621730Sjkh	if ((!name || !strcmp(Devices[i]->name, name)) &&
53721730Sjkh	    (!desc || !strcmp(Devices[i]->description, desc)) &&
53821730Sjkh	    (class == DEVICE_TYPE_ANY || class == Devices[i]->type))
53921730Sjkh	    found[j++] = Devices[i];
54021730Sjkh    }
54121730Sjkh    found[j] = NULL;
54221730Sjkh    return j ? found : NULL;
54321730Sjkh}
54421730Sjkh
5458636Sjkhint
5468636SjkhdeviceCount(Device **devs)
5478636Sjkh{
5488636Sjkh    int i;
5498636Sjkh
5508636Sjkh    if (!devs)
5518636Sjkh	return 0;
5528636Sjkh    for (i = 0; devs[i]; i++);
5538636Sjkh    return i;
5548636Sjkh}
5558636Sjkh
5568262Sjkh/*
5578549Sjkh * Create a menu listing all the devices of a certain type in the system.
5588549Sjkh * The passed-in menu is expected to be a "prototype" from which the new
5598549Sjkh * menu is cloned.
5608262Sjkh */
5618262SjkhDMenu *
56215242SjkhdeviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)(dialogMenuItem *d), int (*check)(dialogMenuItem *d))
5638262Sjkh{
5648549Sjkh    Device **devs;
5658556Sjkh    int numdevs;
5668556Sjkh    DMenu *tmp = NULL;
5678556Sjkh    int i, j;
5688262Sjkh
5698549Sjkh    devs = deviceFind(NULL, type);
57016348Sjkh    numdevs = deviceCount(devs);
57116348Sjkh    if (!numdevs)
5728556Sjkh	return NULL;
57315091Sjkh    tmp = (DMenu *)safe_malloc(sizeof(DMenu) + (sizeof(dialogMenuItem) * (numdevs + 1)));
5748556Sjkh    bcopy(menu, tmp, sizeof(DMenu));
5758556Sjkh    for (i = 0; devs[i]; i++) {
57615091Sjkh	tmp->items[i].prompt = devs[i]->name;
57716348Sjkh	for (j = 0; j < numDevs; j++) {
57816348Sjkh	    if (devs[i] == Devices[j]) {
57916348Sjkh		tmp->items[i].title = Devices[j]->description;
5808556Sjkh		break;
5818549Sjkh	    }
5828262Sjkh	}
58316348Sjkh	if (j == numDevs)
58415091Sjkh	    tmp->items[i].title = "<unknown device type>";
58515091Sjkh	tmp->items[i].fire = hook;
58615242Sjkh	tmp->items[i].checked = check;
5878262Sjkh    }
5888556Sjkh    tmp->items[i].title = NULL;
5898556Sjkh    return tmp;
5908262Sjkh}
591