From 2245fa69bb176119fa09cd4da34443b08fc8d361 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Wed, 24 Jun 2009 23:17:00 +0000 Subject: [PATCH] Make sysinstall search for /dev/daXa and register such devices as USB disks. This covers the common case of unsliced USB drives, and makes it possible to select them as installation source media. PR: 61152, 115197, 135016 Submitted by: randi MFC after: 1 month --- usr.sbin/sysinstall/Makefile | 2 +- usr.sbin/sysinstall/devices.c | 19 +++++++ usr.sbin/sysinstall/dispatch.c | 4 +- usr.sbin/sysinstall/media.c | 46 +++++++++++++++++ usr.sbin/sysinstall/menus.c | 12 +++++ usr.sbin/sysinstall/options.c | 3 ++ usr.sbin/sysinstall/sysinstall.h | 8 +++ usr.sbin/sysinstall/usb.c | 88 ++++++++++++++++++++++++++++++++ 8 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 usr.sbin/sysinstall/usb.c diff --git a/usr.sbin/sysinstall/Makefile b/usr.sbin/sysinstall/Makefile index 5cbd2e54ba87..3f2b75848373 100644 --- a/usr.sbin/sysinstall/Makefile +++ b/usr.sbin/sysinstall/Makefile @@ -11,7 +11,7 @@ SRCS= anonFTP.c cdrom.c command.c config.c devices.c dhcp.c \ ftp.c globals.c http.c index.c install.c installUpgrade.c keymap.c \ label.c main.c makedevs.c media.c menus.c misc.c modules.c \ mouse.c msg.c network.c nfs.c options.c package.c \ - system.c tcpip.c termcap.c ttys.c ufs.c user.c \ + system.c tcpip.c termcap.c ttys.c ufs.c usb.c user.c \ variable.c ${_wizard} keymap.h countries.h CFLAGS+= -DUSE_GZIP=1 diff --git a/usr.sbin/sysinstall/devices.c b/usr.sbin/sysinstall/devices.c index e78c26862f8f..3ba873250069 100644 --- a/usr.sbin/sysinstall/devices.c +++ b/usr.sbin/sysinstall/devices.c @@ -65,6 +65,8 @@ static int numDevs; DEVICE_ENTRY(DEVICE_TYPE_NETWORK, name, descr, 0) #define SERIAL(name, descr, max) \ DEVICE_ENTRY(DEVICE_TYPE_NETWORK, name, descr, max) +#define USB(name, descr, max) \ + DEVICE_ENTRY(DEVICE_TYPE_USB, name, descr, max) static struct _devname { DeviceType type; @@ -89,6 +91,7 @@ static struct _devname { DISK("mfid%d", "LSI MegaRAID SAS array", 4), FLOPPY("fd%d", "floppy drive unit A", 4), SERIAL("cuad%d", "%s on device %s (COM%d)", 16), + USB("da%da", "USB Mass Storage Device", 16), NETWORK("ae", "Attansic/Atheros L2 Fast Ethernet"), NETWORK("age", "Attansic/Atheros L1 Gigabit Ethernet"), NETWORK("alc", "Atheros AR8131/AR8132 PCIe Ethernet"), @@ -392,6 +395,22 @@ deviceGetAll(void) } break; + case DEVICE_TYPE_USB: + fd = deviceTry(device_names[i], try, j); + if (fd >= 0) { + char n[BUFSIZ]; + + close(fd); + snprintf(n, sizeof(n), device_names[i].name, j); + deviceRegister(strdup(n), device_names[i].description, + strdup(try), DEVICE_TYPE_USB, TRUE, mediaInitUSB, + mediaGetUSB, mediaShutdownUSB, NULL); + + if (isDebug()) + msgDebug("Found a USB disk for %s\n", try); + } + break; + case DEVICE_TYPE_NETWORK: fd = deviceTry(device_names[i], try, j); /* The only network devices that you can open this way are serial ones */ diff --git a/usr.sbin/sysinstall/dispatch.c b/usr.sbin/sysinstall/dispatch.c index 79d9cf331fe4..bd22afd0b72e 100644 --- a/usr.sbin/sysinstall/dispatch.c +++ b/usr.sbin/sysinstall/dispatch.c @@ -96,6 +96,7 @@ static struct _word { { "mediaClose", dispatch_mediaClose }, { "mediaSetCDROM", mediaSetCDROM }, { "mediaSetFloppy", mediaSetFloppy }, + { "mediaSetUSB", mediaSetUSB }, { "mediaSetDOS", mediaSetDOS }, { "mediaSetFTP", mediaSetFTP }, { "mediaSetFTPActive", mediaSetFTPActive }, @@ -511,7 +512,8 @@ dispatch_load_menu(dialogMenuItem *self) Device **devlist; char *err; int what, i, j, msize, count; - DeviceType dtypes[] = {DEVICE_TYPE_FLOPPY, DEVICE_TYPE_CDROM, DEVICE_TYPE_DOS, DEVICE_TYPE_UFS}; + DeviceType dtypes[] = {DEVICE_TYPE_FLOPPY, DEVICE_TYPE_CDROM, + DEVICE_TYPE_DOS, DEVICE_TYPE_UFS, DEVICE_TYPE_USB}; fprintf(stderr, "dispatch_load_menu called\n"); diff --git a/usr.sbin/sysinstall/media.c b/usr.sbin/sysinstall/media.c index 643f28b431ae..e50b47c8edd4 100644 --- a/usr.sbin/sysinstall/media.c +++ b/usr.sbin/sysinstall/media.c @@ -220,6 +220,52 @@ mediaSetFloppy(dialogMenuItem *self) return (mediaDevice ? DITEM_LEAVE_MENU : DITEM_FAILURE); } +static int +USBHook(dialogMenuItem *self) +{ + return genericHook(self, DEVICE_TYPE_USB); +} + + +/* + * Attempt to use USB as the installation media type. + */ +int +mediaSetUSB(dialogMenuItem *self) +{ + Device **devs; + int cnt; + + mediaClose(); + devs = deviceFind(NULL, DEVICE_TYPE_USB); + cnt = deviceCount(devs); + + if (!cnt) { + msgConfirm("No USB devices found!"); + return DITEM_FAILURE | DITEM_CONTINUE; + } + else if (cnt > 1) { + DMenu *menu; + int status; + + menu = deviceCreateMenu(&MenuMediaUSB, DEVICE_TYPE_USB, USBHook, + NULL); + if (!menu) + msgFatal("Unable to create USB menu! Something is " \ + "seriously wrong."); + status = dmenuOpenSimple(menu, FALSE); + free(menu); + if (!status) + return DITEM_FAILURE; + } + else + mediaDevice = devs[0]; + if (mediaDevice) + mediaDevice->private = NULL; + msgConfirm("Using USB device: %s", mediaDevice->name); + return (mediaDevice ? DITEM_LEAVE_MENU : DITEM_FAILURE); +} + static int DOSHook(dialogMenuItem *self) { diff --git a/usr.sbin/sysinstall/menus.c b/usr.sbin/sysinstall/menus.c index 7d1210b16a64..152ad32e5bc4 100644 --- a/usr.sbin/sysinstall/menus.c +++ b/usr.sbin/sysinstall/menus.c @@ -191,6 +191,7 @@ DMenu MenuIndex = { { " Media, NFS", "Select NFS installation media.", NULL, mediaSetNFS }, { " Media, Floppy", "Select floppy installation media.", NULL, mediaSetFloppy }, { " Media, CDROM/DVD", "Select CDROM/DVD installation media.", NULL, mediaSetCDROM }, + { " Media, USB", "Select USB installation media.", NULL, mediaSetUSB }, { " Media, DOS", "Select DOS installation media.", NULL, mediaSetDOS }, { " Media, UFS", "Select UFS installation media.", NULL, mediaSetUFS }, { " Media, FTP", "Select FTP installation media.", NULL, mediaSetFTP }, @@ -428,6 +429,16 @@ DMenu MenuMediaFloppy = { { { NULL } }, }; +DMenu MenuMediaUSB = { + DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS, + "Choose a USB drive", + "You have more than one USB drive. Please choose which drive\n" + "you would like to use.", + NULL, + NULL, + { { NULL } }, +}; + DMenu MenuMediaDOS = { DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS, "Choose a DOS partition", @@ -850,6 +861,7 @@ DMenu MenuMedia = { { "6 NFS", "Install over NFS", NULL, mediaSetNFS }, { "7 File System", "Install from an existing filesystem", NULL, mediaSetUFS }, { "8 Floppy", "Install from a floppy disk set", NULL, mediaSetFloppy }, + { "9 USB", "Install from a USB drive", NULL, mediaSetUSB }, { "X Options", "Go to the Options screen", NULL, optionsEditor }, { NULL } }, }; diff --git a/usr.sbin/sysinstall/options.c b/usr.sbin/sysinstall/options.c index 714ff4daebf6..33b50311ff9c 100644 --- a/usr.sbin/sysinstall/options.c +++ b/usr.sbin/sysinstall/options.c @@ -78,6 +78,9 @@ mediaCheck(Option *opt) case DEVICE_TYPE_CDROM: return "CDROM"; + case DEVICE_TYPE_USB: + return "USB"; + case DEVICE_TYPE_DOS: return "DOS"; diff --git a/usr.sbin/sysinstall/sysinstall.h b/usr.sbin/sysinstall/sysinstall.h index 6f860f5b53b7..89827b17083f 100644 --- a/usr.sbin/sysinstall/sysinstall.h +++ b/usr.sbin/sysinstall/sysinstall.h @@ -271,6 +271,7 @@ typedef enum { DEVICE_TYPE_FTP, DEVICE_TYPE_NETWORK, DEVICE_TYPE_CDROM, + DEVICE_TYPE_USB, DEVICE_TYPE_DOS, DEVICE_TYPE_UFS, DEVICE_TYPE_NFS, @@ -440,6 +441,7 @@ extern DMenu MenuMedia; /* Media type menu */ extern DMenu MenuMouse; /* Mouse type menu */ #endif extern DMenu MenuMediaCDROM; /* CDROM media menu */ +extern DMenu MenuMediaUSB; /* USB media menu */ extern DMenu MenuMediaDOS; /* DOS media menu */ extern DMenu MenuMediaFloppy; /* Floppy media menu */ extern DMenu MenuMediaFTP; /* FTP media menu */ @@ -717,6 +719,7 @@ extern void mediaClose(void); extern int mediaTimeout(void); extern int mediaSetCDROM(dialogMenuItem *self); extern int mediaSetFloppy(dialogMenuItem *self); +extern int mediaSetUSB(dialogMenuItem *self); extern int mediaSetDOS(dialogMenuItem *self); extern int mediaSetFTP(dialogMenuItem *self); extern int mediaSetFTPActive(dialogMenuItem *self); @@ -848,6 +851,11 @@ extern void mediaShutdownUFS(Device *dev); extern Boolean mediaInitUFS(Device *dev); extern FILE *mediaGetUFS(Device *dev, char *file, Boolean probe); +/* usb.c */ +extern Boolean mediaInitUSB(Device *dev); +extern FILE *mediaGetUSB(Device *dev, char *file, Boolean probe); +extern void mediaShutdownUSB(Device *dev); + /* user.c */ extern int userAddGroup(dialogMenuItem *self); extern int userAddUser(dialogMenuItem *self); diff --git a/usr.sbin/sysinstall/usb.c b/usr.sbin/sysinstall/usb.c new file mode 100644 index 000000000000..5be8ac11754b --- /dev/null +++ b/usr.sbin/sysinstall/usb.c @@ -0,0 +1,88 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * used floppy.c and cdrom.c as templates, edited as necessary. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include + +#include "sysinstall.h" + +static Boolean USBMounted; +static char mountpoint[] = "/dist"; + +Boolean +mediaInitUSB(Device *dev) +{ + struct ufs_args ufsargs; + + if (USBMounted) + return TRUE; + + Mkdir(mountpoint); + + memset(&ufsargs, 0, sizeof(ufsargs)); + ufsargs.fspec = dev->devname; + + if (mount("ufs", mountpoint, MNT_RDONLY, (caddr_t)&ufsargs) != -1) { + USBMounted = TRUE; + return TRUE; + } + + msgConfirm("Error mounting USB drive %s (%s) on %s : %s", + dev->name, dev->devname, mountpoint, strerror(errno)); + return FALSE; +} + + +FILE * +mediaGetUSB(Device *dev, char *file, Boolean probe) +{ + return mediaGenericGet(mountpoint, file); +} + + +/* + * When sysinstall terminates, all USB drives handled by deviceRegister will + * be checked and unmounted if necessary. + */ +void +mediaShutdownUSB(Device *dev) +{ + if (!USBMounted) + return; + + if (unmount(mountpoint, MNT_FORCE) != 0) + msgConfirm("Could not unmount the USB drive from %s: %s", + mountpoint, strerror(errno)); + else + USBMounted = FALSE; + +}