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