Hello, Damien Zammit, le mar. 27 juin 2023 11:11:09 +0000, a ecrit: > This is mostly a copy of rumpdisk,
It should be possible to share the code, by setting makemode to servers, and using -D / #ifdef? > with small tweaks to > compile in the rump USB stack instead of SATA/IDE. > > This can be tested by running qemu with a USB3 controller as follows: > > -drive if=none,id=usbstick,format=raw,file=/path/to/disk.img \ > -device qemu-xhci \ > -device usb-storage,drive=usbstick \ > > NB: /path/to/disk.img can be a block device on the host. > > Then call grub module rumpusbdisk.static instead of rumpdisk.static > and pass ' root=part:X:device:sd0 noide' as gnumach parameters, > where X is the partition number of / within the disk/image. > > (IRQ sharing still seems broken). > --- > Makefile | 2 +- > rumpusbdisk/Makefile | 42 +++ > rumpusbdisk/block-rumpusb.c | 530 ++++++++++++++++++++++++++++++++++++ > rumpusbdisk/block-rumpusb.h | 23 ++ > rumpusbdisk/ioccom-rump.h | 82 ++++++ > rumpusbdisk/main.c | 148 ++++++++++ > 6 files changed, 826 insertions(+), 1 deletion(-) > create mode 100644 rumpusbdisk/Makefile > create mode 100644 rumpusbdisk/block-rumpusb.c > create mode 100644 rumpusbdisk/block-rumpusb.h > create mode 100644 rumpusbdisk/ioccom-rump.h > create mode 100644 rumpusbdisk/main.c > > diff --git a/Makefile b/Makefile > index 874349c0..154386ba 100644 > --- a/Makefile > +++ b/Makefile > @@ -49,7 +49,7 @@ prog-subdirs = auth proc exec term \ > shutdown > > ifeq ($(HAVE_LIBRUMP),yes) > -prog-subdirs += rumpdisk > +prog-subdirs += rumpdisk rumpusbdisk > endif > > ifeq ($(HAVE_SUN_RPC),yes) > diff --git a/rumpusbdisk/Makefile b/rumpusbdisk/Makefile > new file mode 100644 > index 00000000..de6374b9 > --- /dev/null > +++ b/rumpusbdisk/Makefile > @@ -0,0 +1,42 @@ > +# > +# Copyright (C) 2023 Free Software Foundation, Inc. > +# > +# This program is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation; either version 2, or (at > +# your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, but > +# WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +# General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + > +RUMPLIBS=rump rumpuser rumpdev rumpdev_disk rumpdev_pci rumpvfs rumpdev_usb > rumpdev_pci_usbhc rumpdev_umass > +RUMPEXTRA=rumpdev_scsipi > + > +# If we have a configured tree, include the configuration so that we > +# can conditionally build translators. > +ifneq (,$(wildcard ../config.make)) > + include ../config.make > +endif > + > +ifeq ($(HAVE_LIBRUMP_VFSNOFIFO),yes) > +RUMPLIBS += rumpvfs_nofifofs > +endif > + > +dir := rumpusbdisk > +makemode := server > + > +SRCS = main.c block-rumpusb.c > +LCLHDRS = block-rumpusb.h ioccom-rump.h > +target = rumpusbdisk > +OBJS = $(SRCS:.c=.o) > +HURDLIBS = machdev ports trivfs shouldbeinlibc iohelp ihash fshelp > +LDLIBS += -lpthread -lpciaccess -ldl > +LDLIBS += -Wl,--whole-archive $(RUMPLIBS:%=-l%_pic) -Wl,--no-whole-archive > $(RUMPEXTRA:%=-l%_pic) > + > +include ../Makeconf > diff --git a/rumpusbdisk/block-rumpusb.c b/rumpusbdisk/block-rumpusb.c > new file mode 100644 > index 00000000..1b249baa > --- /dev/null > +++ b/rumpusbdisk/block-rumpusb.c > @@ -0,0 +1,530 @@ > +/* > + * Rump usb block driver support > + * > + * Copyright (C) 2023 Free Software Foundation > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2, or (at your option) > + * any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#include <ctype.h> > +#include <stdio.h> > +#include <stdbool.h> > +#include <string.h> > +#include <unistd.h> > +#include <sys/mman.h> > + > +#include <mach.h> > +#include <mach/gnumach.h> > +#include <hurd.h> > +#include <hurd/ports.h> > +#include <device/device.h> > + > +#define MACH_INCLUDE > +#define _STANDALONE > + > +#include "libmachdev/machdev.h" > +#include <rump/rump.h> > +#include <rump/rump_syscalls.h> > +#include <rump/rumperrno2host.h> > + > +#include "ioccom-rump.h" > +#define DIOCGMEDIASIZE _IOR('d', 132, off_t) > +#define DIOCGSECTORSIZE _IOR('d', 133, unsigned int) > + > +#define BLKRRPART 0x125F /* re-read partition table */ > + > +#define DISK_NAME_LEN 32 > +#define MAX_DISK_DEV 2 > + > +static bool disabled; > + > +static mach_port_t master_host; > + > +/* rwlock to protect concurrent close while reading/writing */ > +pthread_rwlock_t rumpusbdisk_rwlock = PTHREAD_RWLOCK_INITIALIZER; > + > +/* One of these is associated with each open instance of a device. */ > +struct block_data > +{ > + struct port_info port; /* device port */ > + struct machdev_emul_device device; /* generic device structure */ > + dev_mode_t mode; /* r/w etc */ > + int rump_fd; /* block device fd handle */ > + char name[DISK_NAME_LEN]; /* eg /dev/sd0 */ > + off_t media_size; /* total block device size */ > + uint32_t block_size; /* size in bytes of 1 sector */ > + int taken; /* refcount */ > + struct block_data *next; > +}; > + > +/* Return a send right associated with network device ND. */ > +static mach_port_t > +rumpusbdisk_dev_to_port (void *nd) > +{ > + return (nd ? ports_get_send_right (nd) : MACH_PORT_NULL); > +} > + > +static struct block_data *block_head; > +static struct machdev_device_emulation_ops rumpusb_block_emulation_ops; > + > +static struct block_data * > +search_bd (const char *name) > +{ > + struct block_data *bd = block_head; > + > + while (bd) > + { > + /* Check name and refcount > 0 */ > + if (!strcmp (bd->name, name) && bd->taken) > + return bd; > + bd = bd->next; > + } > + return NULL; > +} > + > +/* BSD name of whole disk device is /dev/rwdXd > + * but we will receive wdX as the name */ > +static void > +translate_name (char *output, int len, const char *name) > +{ > + snprintf (output, len - 1, "/dev/r%sd", name); > +} > + > +static boolean_t > +is_disk_device (const char *name) > +{ > + const char *dev; > + const char *allowed_devs[MAX_DISK_DEV] = { > + "sd", > + "cd" > + }; > + uint8_t i; > + > + for (i = 0; i < MAX_DISK_DEV; i++) > + { > + dev = allowed_devs[i]; > + /* /dev/XXN but we only care about /dev/XX prefix */ > + if (! strncmp (dev, name, strlen(dev))) > + return TRUE; > + } > + return FALSE; > +} > + > +static int > +dev_mode_to_rump_mode (const dev_mode_t mode) > +{ > + int ret = 0; > + if (mode & D_READ) > + { > + if (mode & D_WRITE) > + ret = RUMP_O_RDWR; > + else > + ret = RUMP_O_RDONLY; > + } > + else > + { > + if (mode & D_WRITE) > + ret = RUMP_O_WRONLY; > + } > + return ret; > +} > + > +static void > +rumpusbdisk_device_init (void) > +{ > + mach_port_t device_master; > + > + if (! get_privileged_ports (&master_host, &device_master)) > + { > + device_t device; > + > + if (! device_open (device_master, D_READ, "sd0", &device) > + || ! device_open (device_master, D_READ, "sd1", &device) > + || ! device_open (device_master, D_READ, "sd2", &device) > + || ! device_open (device_master, D_READ, "sd3", &device)) > + { > + device_close (device); > + mach_port_deallocate (mach_task_self (), device); > + fprintf(stderr, "Kernel is already driving a SATA device, skipping > probing usb disks\n"); > + fflush(stderr); > + disabled = 1; > + return; > + } > + } > + rump_init (); > +} > + > +static io_return_t > +rumpusbdisk_device_close (void *d) > +{ > + struct block_data *bd = d; > + io_return_t err; > + > + pthread_rwlock_wrlock (&rumpusbdisk_rwlock); > + > + bd->taken--; > + if (bd->taken) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > + } > + > + err = rump_errno2host (rump_sys_close (bd->rump_fd)); > + if (err != D_SUCCESS) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return err; > + } > + > + ports_port_deref (bd); > + ports_destroy_right (bd); > + > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > +} > + > +static void > +rumpusbdisk_device_dealloc (void *d) > +{ > + rump_sys_reboot (0, NULL); > +} > + > +static void > +rumpusbdisk_device_sync (void) > +{ > + if (disabled) > + return; > + > + rump_sys_sync (); > +} > + > +static io_return_t > +rumpusbdisk_device_open (mach_port_t reply_port, mach_msg_type_name_t > reply_port_type, > + dev_mode_t mode, const char *name, device_t * devp, > + mach_msg_type_name_t * devicePoly) > +{ > + io_return_t err; > + int ret, fd; > + struct block_data *bd; > + char dev_name[DISK_NAME_LEN]; > + off_t media_size; > + uint32_t block_size; > + > + if (disabled) > + return D_NO_SUCH_DEVICE; > + > + if (! is_disk_device (name)) > + return D_NO_SUCH_DEVICE; > + > + /* Protect against concurrent open/close */ > + pthread_rwlock_wrlock (&rumpusbdisk_rwlock); > + > + /* Find previous device or open if new */ > + bd = search_bd (name); > + if (bd) > + { > + bd->taken++; > + *devp = ports_get_right (bd); > + *devicePoly = MACH_MSG_TYPE_MAKE_SEND; > + > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > + } > + > + translate_name (dev_name, DISK_NAME_LEN, name); > + > + fd = rump_sys_open (dev_name, dev_mode_to_rump_mode (mode)); > + if (fd < 0) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (errno); > + } > + > + ret = rump_sys_ioctl (fd, DIOCGMEDIASIZE, &media_size); > + if (ret < 0) > + { > + mach_print ("DIOCGMEDIASIZE ioctl fails\n"); > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (errno); > + } > + > + ret = rump_sys_ioctl (fd, DIOCGSECTORSIZE, &block_size); > + if (ret < 0) > + { > + mach_print ("DIOCGSECTORSIZE ioctl fails\n"); > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (errno); > + } > + > + err = machdev_create_device_port (sizeof (*bd), &bd); > + if (err != 0) > + { > + rump_sys_close (fd); > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return err; > + } > + > + bd->taken = 1; > + snprintf (bd->name, DISK_NAME_LEN, "%s", name); > + bd->rump_fd = fd; > + bd->mode = mode; > + bd->device.emul_data = bd; > + bd->device.emul_ops = &rumpusb_block_emulation_ops; > + bd->media_size = media_size; > + bd->block_size = block_size; > + > + bd->next = block_head; > + block_head = bd; > + > + *devp = ports_get_right (bd); > + *devicePoly = MACH_MSG_TYPE_MAKE_SEND; > + > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > +} > + > +static io_return_t > +rumpusbdisk_device_write (void *d, mach_port_t reply_port, > + mach_msg_type_name_t reply_port_type, dev_mode_t mode, > + recnum_t bn, io_buf_ptr_t data, unsigned int count, > + int *bytes_written) > +{ > + struct block_data *bd = d; > + ssize_t written; > + int pagesize = sysconf (_SC_PAGE_SIZE); > + > + if ((bd->mode & D_WRITE) == 0) > + return D_INVALID_OPERATION; > + > + pthread_rwlock_rdlock (&rumpusbdisk_rwlock); > + /* Ensure device is still open */ > + if (! bd->taken) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_INVALID_OPERATION; > + } > + > + if ((vm_offset_t) data % pagesize) > + { > + /* Not aligned, have to copy to aligned buffer. */ > + vm_address_t buf; > + rpc_phys_addr_t pap; > + kern_return_t ret; > + int err; > + > + /* While at it, make it contiguous */ > + ret = vm_allocate_contiguous (master_host, mach_task_self (), &buf, > &pap, count, 0, 0x100000000ULL, 0); > + if (ret != KERN_SUCCESS) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return ENOMEM; > + } > + > + memcpy ((void*) buf, data, count); > + > + written = rump_sys_pwrite (bd->rump_fd, (const void *)buf, > (size_t)count, (off_t)bn * bd->block_size); > + err = errno; > + > + vm_deallocate (mach_task_self (), (vm_address_t) buf, count); > + > + if (written < 0) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (err); > + } > + } > + else > + { > + volatile uint8_t dummy_read __attribute__ ((unused)); > + int npages = (count + pagesize - 1) / pagesize; > + int i; > + > + /* Fault-in the memory pages by reading a single byte of each */ > + for (i = 0; i < npages; i++) > + dummy_read = ((volatile uint8_t *)data)[i * pagesize]; > + > + /* XXX: _bus_dmamap_load_buffer seems not to call > rumpcomp_pci_virt_to_mach > + * for each page, so separate out pages ourselves :/ */ > + written = 0; > + while (written < count) > + { > + size_t todo = count - written; > + ssize_t done; > + > + if (todo > pagesize) > + todo = pagesize; > + > + done = rump_sys_pwrite (bd->rump_fd, (const void *)data + written, > todo, (off_t)bn * bd->block_size + written); > + > + if (done < 0) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (errno); > + } > + > + written += done; > + } > + } > + > + vm_deallocate (mach_task_self (), (vm_address_t) data, count); > + > + *bytes_written = (int)written; > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > +} > + > +static io_return_t > +rumpusbdisk_device_read (void *d, mach_port_t reply_port, > + mach_msg_type_name_t reply_port_type, dev_mode_t mode, > + recnum_t bn, int count, io_buf_ptr_t * data, > + unsigned *bytes_read) > +{ > + struct block_data *bd = d; > + vm_address_t buf; > + int pagesize = sysconf (_SC_PAGE_SIZE); > + int npages = (count + pagesize - 1) / pagesize; > + int i; > + ssize_t done, err; > + kern_return_t ret; > + > + if ((bd->mode & D_READ) == 0) > + return D_INVALID_OPERATION; > + > + if (count == 0) > + return D_SUCCESS; > + > + pthread_rwlock_rdlock (&rumpusbdisk_rwlock); > + /* Ensure device is still open */ > + if (! bd->taken) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_INVALID_OPERATION; > + } > + > + /* TODO: directly write at *data when it is aligned */ > + *data = 0; > + ret = vm_allocate (mach_task_self (), &buf, npages * pagesize, TRUE); > + if (ret != KERN_SUCCESS) > + { > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return ENOMEM; > + } > + > + /* Ensure physical allocation by writing a single byte of each */ > + for (i = 0; i < npages; i++) > + ((uint8_t *)buf)[i * pagesize] = 0; > + > + /* XXX: _bus_dmamap_load_buffer seems not to call rumpcomp_pci_virt_to_mach > + * for each page, so separate out pages ourselves :/ */ > + done = 0; > + while (done < count) > + { > + size_t todo = count - done; > + > + if (todo > pagesize) > + todo = pagesize; > + > + err = rump_sys_pread (bd->rump_fd, (void *)buf + done, todo, (off_t)bn > * bd->block_size + done); > + if (err < 0) > + { > + err = errno; > + vm_deallocate (mach_task_self (), buf, npages * pagesize); > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return rump_errno2host (err); > + } > + > + done += err; > + } > + > + *bytes_read = done; > + *data = (void*) buf; > + pthread_rwlock_unlock (&rumpusbdisk_rwlock); > + return D_SUCCESS; > +} > + > +static io_return_t > +rumpusbdisk_device_set_status (void *d, dev_flavor_t flavor, dev_status_t > status, > + mach_msg_type_number_t status_count) > +{ > + switch (flavor) > + { > + case BLKRRPART: > + /* Partitions are not implemented here, but in the parted-based > + * translators. */ > + return D_SUCCESS; > + default: > + return D_INVALID_OPERATION; > + } > +} > + > +static io_return_t > +rumpusbdisk_device_get_status (void *d, dev_flavor_t flavor, dev_status_t > status, > + mach_msg_type_number_t * count) > +{ > + struct block_data *bd = d; > + > + switch (flavor) > + { > + case DEV_GET_SIZE: > + status[DEV_GET_SIZE_RECORD_SIZE] = bd->block_size; > + status[DEV_GET_SIZE_DEVICE_SIZE] = bd->media_size; > + *count = 2; > + break; > + case DEV_GET_RECORDS: > + status[DEV_GET_RECORDS_RECORD_SIZE] = bd->block_size; > + status[DEV_GET_RECORDS_DEVICE_RECORDS] = > + bd->media_size / (unsigned long long) bd->block_size; > + *count = 2; > + break; > + default: > + return D_INVALID_OPERATION; > + } > + return D_SUCCESS; > +} > + > +/* FIXME: > + * Long term strategy: > + * > + * Call rump_sys_aio_read/write and return MIG_NO_REPLY from > + * device_read/write, and send the mig reply once the aio request has > + * completed. That way, only the aio request will be kept in rumpusbdisk > + * memory instead of a whole thread structure. > + */ > +static struct machdev_device_emulation_ops rumpusb_block_emulation_ops = { > + rumpusbdisk_device_init, > + NULL, > + rumpusbdisk_device_dealloc, > + rumpusbdisk_dev_to_port, > + rumpusbdisk_device_open, > + rumpusbdisk_device_close, > + rumpusbdisk_device_write, > + NULL, > + rumpusbdisk_device_read, > + NULL, > + rumpusbdisk_device_set_status, > + rumpusbdisk_device_get_status, > + NULL, > + NULL, > + NULL, > + NULL, > + NULL, > + rumpusbdisk_device_sync > +}; > + > +void > +rump_register_block (void) > +{ > + machdev_register (&rumpusb_block_emulation_ops); > +} > diff --git a/rumpusbdisk/block-rumpusb.h b/rumpusbdisk/block-rumpusb.h > new file mode 100644 > index 00000000..693f35a6 > --- /dev/null > +++ b/rumpusbdisk/block-rumpusb.h > @@ -0,0 +1,23 @@ > +/* > + * Copyright (C) 2023 Free Software Foundation > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2, or (at your option) > + * any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > +#ifndef _BLOCK_RUMPUSB_H_ > +#define _BLOCK_RUMPUSB_H_ > + > +void rump_register_block (void); > + > +#endif > diff --git a/rumpusbdisk/ioccom-rump.h b/rumpusbdisk/ioccom-rump.h > new file mode 100644 > index 00000000..6f41b05b > --- /dev/null > +++ b/rumpusbdisk/ioccom-rump.h > @@ -0,0 +1,82 @@ > +/* $NetBSD: ioccom.h,v 1.12 2014/12/10 00:16:05 christos Exp $ */ > + > +/*- > + * Copyright (c) 1982, 1986, 1990, 1993, 1994 > + * 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. > + * > + * @(#)ioccom.h 8.3 (Berkeley) 1/9/95 > + */ > + > +#ifndef _SYS_IOCCOM_H_ > +#define _SYS_IOCCOM_H_ > + > +/* > + * Ioctl's have the command encoded in the lower word, and the size of > + * any in or out parameters in the upper word. The high 3 bits of the > + * upper word are used to encode the in/out status of the parameter. > + * > + * 31 29 28 16 15 8 7 0 > + * +---------------------------------------------------------------+ > + * | I/O | Parameter Length | Command Group | Command | > + * +---------------------------------------------------------------+ > + */ > +#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 > bits */ > +#define IOCPARM_SHIFT 16 > +#define IOCGROUP_SHIFT 8 > +#define IOCPARM_LEN(x) (((x) >> IOCPARM_SHIFT) & IOCPARM_MASK) > +#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << IOCPARM_SHIFT)) > +#define IOCGROUP(x) (((x) >> IOCGROUP_SHIFT) & 0xff) > + > +#define IOCPARM_MAX NBPG /* max size of ioctl args, mult. of > NBPG */ > + /* no parameters */ > +#define IOC_VOID (unsigned long)0x20000000 > + /* copy parameters out */ > +#define IOC_OUT (unsigned long)0x40000000 > + /* copy parameters in */ > +#define IOC_IN (unsigned long)0x80000000 > + /* copy parameters in and out */ > +#define IOC_INOUT (IOC_IN|IOC_OUT) > + /* mask for IN/OUT/VOID */ > +#define IOC_DIRMASK (unsigned long)0xe0000000 > + > +#define _IOC(inout, group, num, len) \ > + ((inout) | (((len) & IOCPARM_MASK) << IOCPARM_SHIFT) | \ > + ((group) << IOCGROUP_SHIFT) | (num)) > +#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) > +#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) > +#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) > +/* this should be _IORW, but stdio got there first */ > +#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) > + > +#define IOCSNPRINTF(buf, len, cmd) \ > + snprintf((buf), (len), "_IO%s%s('%c', %hhu)", \ > + (((cmd) >> 30) & 1) ? "W" : "", \ > + (((cmd) >> 30) & 2) ? "R" : "", \ > + (char)IOCGROUP(cmd), (unsigned char)(cmd)) > + > + > +#endif /* !_SYS_IOCCOM_H_ */ > diff --git a/rumpusbdisk/main.c b/rumpusbdisk/main.c > new file mode 100644 > index 00000000..d5257683 > --- /dev/null > +++ b/rumpusbdisk/main.c > @@ -0,0 +1,148 @@ > +/* > + * Copyright (C) 2023 Free Software Foundation > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2, or (at your option) > + * any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#include <stdarg.h> > +#include <stdio.h> > +#include <fcntl.h> > +#include <unistd.h> > +#include <stdlib.h> > +#include <string.h> > +#include <error.h> > +#include <argp.h> > +#include <version.h> > + > +#include "libmachdev/machdev.h" > +#include "libshouldbeinlibc/wire.h" > +#include "block-rumpusb.h" > +#include <pthread.h> > +#include <mach.h> > + > +mach_port_t bootstrap_resume_task = MACH_PORT_NULL; > + > +static const struct argp_option options[] = { > + {"host-priv-port", 'h', "PORT", 0, "Host private port PORT"}, > + {"device-master-port",'d', "PORT", 0, "Device master port PORT"}, > + {"next-task", 'N', "TASK", 0, "Next bootstrap task TASK"}, > + {0} > +}; > + > + > +/* Parse a command line option. */ > +static error_t > +parse_opt (int key, char *arg, struct argp_state *state) > +{ > + /* We save our parsed values in this structure, hung off STATE->hook. > + Only after parsing all options successfully will we use these values. > */ > + struct > + { > + int host_priv; > + int dev_master; > + int next_task; > + } *values = state->hook; > + > + switch (key) > + { > + case 'h': > + values->host_priv = atoi(arg); > + break; > + case 'd': > + values->dev_master = atoi(arg); > + break; > + case 'N': > + values->next_task = atoi(arg); > + break; > + > + case ARGP_KEY_INIT: > + state->child_inputs[0] = state->input; > + values = malloc (sizeof *values); > + if (values == 0) > + return ENOMEM; > + state->hook = values; > + memset (values, 0, sizeof *values); > + break; > + > + case ARGP_KEY_SUCCESS: > + /* All options parsed successfully */ > + _hurd_host_priv = values->host_priv; > + _hurd_device_master = values->dev_master; > + bootstrap_resume_task = values->next_task; > + break; > + > + default: > + return ARGP_ERR_UNKNOWN; > + } > + return 0; > +} > + > +static struct argp_child empty_argp_children[] = {{0}}; > +static struct argp rumpusbdisk_argp = {options, parse_opt, 0, 0, > empty_argp_children}; > +static const struct argp *rumpusbdisk_argp_bootup = &rumpusbdisk_argp; > + > +static void * > +rumpusbdisk_multithread_server(void *arg) > +{ > + do > + { > + ports_manage_port_operations_multithread (machdev_device_bucket, > + machdev_demuxer, > + 1000 * 60 * 2, /* 2 minute > thread */ > + 1000 * 60 * 10, /* 10 minute > server */ > + 0); > + } while (1); > + > + return NULL; > +} > + > +int > +main (int argc, char **argv) > +{ > + mach_port_t bootstrap = MACH_PORT_NULL; > + int err; > + pthread_t t; > + > + setenv ("RUMP_NCPU", "1", 1); > + setenv ("RUMP_VERBOSE", "1", 1); > + setenv ("RUMP_HOSTNAME", "HURD0", 1); > + setenv ("HOSTNAME", "HURD0", 1); > + setenv ("RUMP_PANIC", "1", 1); > + > + err = argp_parse (rumpusbdisk_argp_bootup, argc, argv, 0, 0, NULL); > + if (err) > + { > + error(1, err, "Missing parameters for bootstrap"); > + } > + > + rump_register_block (); > + machdev_trivfs_init (argc, argv, bootstrap_resume_task, "rumpusbdisk", > "/dev/rumpusbdisk", &bootstrap); > + > + /* Make sure we will not swap out, in case we drive the disk used for > + swapping. */ > + err = wire_task_self (); > + if (err) > + error (1, errno, "cannot lock all memory"); > + > + machdev_device_init (); > + err = pthread_create (&t, NULL, rumpusbdisk_multithread_server, NULL); > + if (err) > + return err; > + pthread_detach (t); > + machdev_trivfs_server_startup (bootstrap); > + machdev_trivfs_server_loop (NULL); > + /* Never reached */ > + return 0; > +} > -- > 2.40.1 > > > -- Samuel --- Pour une évaluation indépendante, transparente et rigoureuse ! Je soutiens la Commission d'Évaluation de l'Inria.