From owner-freebsd-hackers Tue Mar 5 2: 2:39 2002 Delivered-To: freebsd-hackers@freebsd.org Received: from alcatraz.iptelecom.net.ua (alcatraz.iptelecom.net.ua [212.9.224.15]) by hub.freebsd.org (Postfix) with ESMTP id 9900337B400; Tue, 5 Mar 2002 02:00:48 -0800 (PST) Received: from ipcard.iptcom.net (ipcard.iptcom.net [212.9.224.5]) by alcatraz.iptelecom.net.ua (8.9.3/8.9.3) with ESMTP id MAA13740; Tue, 5 Mar 2002 12:00:38 +0200 (EET) (envelope-from sobomax@FreeBSD.org) Received: from vega.vega.com (h34.229.dialup.iptcom.net [212.9.229.34]) by ipcard.iptcom.net (8.9.3/8.9.3) with ESMTP id MAA16763; Tue, 5 Mar 2002 12:00:30 +0200 (EET) (envelope-from sobomax@FreeBSD.org) Received: from FreeBSD.org (big_brother.vega.com [192.168.1.1]) by vega.vega.com (8.11.6/8.11.3) with ESMTP id g259xwB02794; Tue, 5 Mar 2002 11:59:58 +0200 (EET) (envelope-from sobomax@FreeBSD.org) Message-ID: <3C84974D.37F683BD@FreeBSD.org> Date: Tue, 05 Mar 2002 12:00:45 +0200 From: Maxim Sobolev Organization: Vega International Capital X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U) X-Accept-Language: en,uk,ru MIME-Version: 1.0 To: hackers@FreeBSD.org, audit@FreeBSD.org, re@FreeBSD.org Subject: Extending loader(8) for loading kerels/modules split across several disks Content-Type: multipart/mixed; boundary="------------C69442EE275E6B52E76568F1" Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG This is a multi-part message in MIME format. --------------C69442EE275E6B52E76568F1 Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 7bit Hi folks, Please review attached patch, which adds long overdue feature to our loader(8), allowing it to load sequence of files as a single object. This should allow us to lift 1.44M limit on compressed kernel for the installation diskette. Please note, that to use this feature to load gzip-compressed objects you need to split the object first and then compress each piece individually, not compress first and then split already compressed file. Therefore tight fitting of each piece to the 1.44M limit could be a little tricky, but not impossible. Other way around is to use kgzip(8) utility to compress kernel and then split it into pieces 1.44M each. If there are no objections I would like to commit it ASAP, so that our RE team is able to use this feature in the forthcoming 5.0-DP1 release. Any feedback is appreciated. -Maxim --------------C69442EE275E6B52E76568F1 Content-Type: text/plain; charset=koi8-r; name="loader-multifiles.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="loader-multifiles.diff" Index: src/lib/libstand/close.c =================================================================== RCS file: /home/ncvs/src/lib/libstand/close.c,v retrieving revision 1.3 diff -d -u -r1.3 close.c --- src/lib/libstand/close.c 30 Sep 2001 22:28:00 -0000 1.3 +++ src/lib/libstand/close.c 5 Mar 2002 09:22:00 -0000 @@ -88,6 +88,7 @@ if (f->f_devdata != NULL) devclose(f); f->f_flags = 0; + f->f_udata = NULL; if (err1) { errno = err1; return (-1); Index: src/lib/libstand/open.c =================================================================== RCS file: /home/ncvs/src/lib/libstand/open.c,v retrieving revision 1.6 diff -d -u -r1.6 open.c --- src/lib/libstand/open.c 30 Sep 2001 22:28:01 -0000 1.6 +++ src/lib/libstand/open.c 5 Mar 2002 09:22:00 -0000 @@ -108,6 +108,7 @@ f->f_ops = (struct fs_ops *)0; f->f_offset = 0; f->f_devdata = NULL; + f->f_udata = NULL; file = (char *)0; error = devopen(f, fname, &file); if (error || Index: src/lib/libstand/stand.h =================================================================== RCS file: /home/ncvs/src/lib/libstand/stand.h,v retrieving revision 1.28 diff -d -u -r1.28 stand.h --- src/lib/libstand/stand.h 18 Feb 2002 20:35:19 -0000 1.28 +++ src/lib/libstand/stand.h 5 Mar 2002 09:22:00 -0000 @@ -164,6 +164,7 @@ char *f_rabuf; /* readahead buffer pointer */ size_t f_ralen; /* valid data in readahead buffer */ off_t f_raoffset; /* consumer offset in readahead buffer */ + void *f_udata; /* user data */ #define SOPEN_RASIZE 512 }; Index: src/sys/boot/alpha/libalpha/alpha_copy.c =================================================================== RCS file: /home/ncvs/src/sys/boot/alpha/libalpha/alpha_copy.c,v retrieving revision 1.5 diff -d -u -r1.5 alpha_copy.c --- src/sys/boot/alpha/libalpha/alpha_copy.c 3 Aug 2000 09:49:44 -0000 1.5 +++ src/sys/boot/alpha/libalpha/alpha_copy.c 5 Mar 2002 09:22:00 -0000 @@ -33,6 +33,7 @@ #include #include "libalpha.h" +#include "sread.h" ssize_t alpha_copyin(const void *src, vm_offset_t dest, const size_t len) @@ -51,7 +52,7 @@ ssize_t alpha_readin(const int fd, vm_offset_t dest, const size_t len) { - return(read(fd, (void *) dest, len)); + return(sread(fd, (void *) dest, len)); } Index: src/sys/boot/common/Makefile.inc =================================================================== RCS file: /home/ncvs/src/sys/boot/common/Makefile.inc,v retrieving revision 1.12 diff -d -u -r1.12 Makefile.inc --- src/sys/boot/common/Makefile.inc 27 Mar 2001 11:59:21 -0000 1.12 +++ src/sys/boot/common/Makefile.inc 5 Mar 2002 09:22:00 -0000 @@ -2,7 +2,7 @@ SRCS+= bcache.c boot.c commands.c console.c devopen.c interp.c SRCS+= interp_backslash.c interp_parse.c load_aout.c load_elf.c ls.c misc.c -SRCS+= module.c panic.c +SRCS+= module.c panic.c sread.c .if defined(LOADER_NET_SUPPORT) SRCS+= dev_net.c Index: src/sys/boot/common/boot.c =================================================================== RCS file: /home/ncvs/src/sys/boot/common/boot.c,v retrieving revision 1.28 diff -d -u -r1.28 boot.c --- src/sys/boot/common/boot.c 11 Sep 2001 01:09:19 -0000 1.28 +++ src/sys/boot/common/boot.c 5 Mar 2002 09:22:00 -0000 @@ -65,7 +65,7 @@ } /* find/load the kernel module */ - if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0) + if (mod_loadkld(1, argv + 1, argc - 2, argv + 2) != 0) return(CMD_ERROR); /* we have consumed all arguments */ argc = 1; @@ -340,11 +340,11 @@ static int loadakernel(int try, int argc, char* argv[]) { - char *cp; + char *filesv[1]; - for (try = 0; (cp = getbootfile(try)) != NULL; try++) - if (mod_loadkld(cp, argc - 1, argv + 1) != 0) - printf("can't load '%s'\n", cp); + for (try = 0; (filesv[0] = getbootfile(try)) != NULL; try++) + if (mod_loadkld(1, filesv, argc - 1, argv + 1) != 0) + printf("can't load '%s'\n", filesv[0]); else return 1; return 0; Index: src/sys/boot/common/bootstrap.h =================================================================== RCS file: /home/ncvs/src/sys/boot/common/bootstrap.h,v retrieving revision 1.35 diff -d -u -r1.35 bootstrap.h --- src/sys/boot/common/bootstrap.h 25 Feb 2002 04:31:25 -0000 1.35 +++ src/sys/boot/common/bootstrap.h 5 Mar 2002 09:22:00 -0000 @@ -210,7 +210,7 @@ struct file_format { /* Load function must return EFTYPE if it can't handle the module supplied */ - int (* l_load)(char *filename, vm_offset_t dest, struct preloaded_file **result); + int (* l_load)(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result); /* Only a loader that will load a kernel (first module) should have an exec handler */ int (* l_exec)(struct preloaded_file *mp); }; @@ -218,9 +218,8 @@ extern struct file_format *file_formats[]; /* supplied by consumer */ extern struct preloaded_file *preloaded_files; -int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]); -int mod_loadobj(char *type, char *name); -int mod_loadkld(const char *name, int argc, char *argv[]); +int mod_load(int filesc, char *filesv[], struct mod_depend *verinfo, int argc, char *argv[]); +int mod_loadkld(int filesc, char *filesv[], int argc, char *argv[]); struct preloaded_file *file_alloc(void); struct preloaded_file *file_findfile(char *name, char *type); @@ -232,10 +231,10 @@ /* MI module loaders */ -int aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); +int aout_loadfile(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result); vm_offset_t aout_findsym(char *name, struct preloaded_file *fp); -int elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); +int elf_loadfile(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result); /* * Support for commands Index: src/sys/boot/common/load_aout.c =================================================================== RCS file: /home/ncvs/src/sys/boot/common/load_aout.c,v retrieving revision 1.20 diff -d -u -r1.20 load_aout.c --- src/sys/boot/common/load_aout.c 11 Sep 2001 01:09:19 -0000 1.20 +++ src/sys/boot/common/load_aout.c 5 Mar 2002 09:22:06 -0000 @@ -39,6 +39,7 @@ #include #include "bootstrap.h" +#include "sread.h" static int aout_loadimage(struct preloaded_file *fp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel); @@ -56,7 +57,7 @@ * will be saved in (result). */ int -aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result) +aout_loadfile(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result) { struct preloaded_file *fp, *kfp; struct exec ehdr; @@ -70,11 +71,11 @@ /* * Open the image, read and validate the a.out header */ - if (filename == NULL) /* can't handle nameless */ + if (filesv[0] == NULL) /* can't handle nameless */ return(EFTYPE); - if ((fd = open(filename, O_RDONLY)) == -1) + if ((fd = sopen(filesc, filesv, O_RDONLY)) == -1) return(errno); - if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { + if (sread(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; } @@ -132,8 +133,8 @@ */ fp = file_alloc(); if (kernel) - setenv("kernelname", filename, 1); - fp->f_name = strdup(filename); + setenv("kernelname", filesv[0], 1); + fp->f_name = strdup(filesv[0]); fp->f_type = strdup(kernel ? aout_kerneltype : aout_moduletype); /* Page-align the load address */ @@ -145,7 +146,7 @@ } fp->f_addr = addr; /* save the aligned load address */ if (kernel) - printf("%s at %p\n", filename, (void *) addr); + printf("%s at %p\n", filesv[0], (void *) addr); fp->f_size = aout_loadimage(fp, fd, addr, &ehdr, kernel); if (fp->f_size == 0) @@ -170,7 +171,7 @@ oerr: file_discard(fp); out: - close(fd); + sclose(fd); return(err); } @@ -191,7 +192,7 @@ vm_offset_t ssym, esym; addr = loadaddr; - lseek(fd, (off_t)N_TXTOFF(*ehdr), SEEK_SET); + slseek(fd, (off_t)N_TXTOFF(*ehdr), SEEK_SET); /* text segment */ printf(" text=0x%lx ", ehdr->a_text); @@ -232,7 +233,7 @@ addr += ehdr->a_syms; /* string table */ - read(fd, &ss, sizeof(ss)); + sread(fd, &ss, sizeof(ss)); archsw.arch_copyin(&ss, addr, sizeof(ss)); addr += sizeof(ss); ss -= sizeof(ss); Index: src/sys/boot/common/load_elf.c =================================================================== RCS file: /home/ncvs/src/sys/boot/common/load_elf.c,v retrieving revision 1.21 diff -d -u -r1.21 load_elf.c --- src/sys/boot/common/load_elf.c 11 Sep 2001 01:09:19 -0000 1.21 +++ src/sys/boot/common/load_elf.c 5 Mar 2002 09:22:06 -0000 @@ -40,6 +40,7 @@ #include #include "bootstrap.h" +#include "sread.h" #define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) @@ -76,7 +77,7 @@ * will be saved in (result). */ int -elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result) +elf_loadfile(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result) { struct preloaded_file *fp, *kfp; struct elf_file ef; @@ -91,16 +92,16 @@ /* * Open the image, read and validate the ELF header */ - if (filename == NULL) /* can't handle nameless */ + if (filesv[0] == NULL) /* can't handle nameless */ return(EFTYPE); - if ((ef.fd = open(filename, O_RDONLY)) == -1) + if ((ef.fd = sopen(filesc, filesv, O_RDONLY)) == -1) return(errno); ef.firstpage = malloc(PAGE_SIZE); if (ef.firstpage == NULL) { - close(ef.fd); + sclose(ef.fd); return(ENOMEM); } - bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE); + bytes_read = sread(ef.fd, ef.firstpage, PAGE_SIZE); ef.firstlen = (size_t)bytes_read; if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ @@ -181,15 +182,15 @@ goto out; } if (ef.kernel) - setenv("kernelname", filename, 1); - fp->f_name = strdup(filename); + setenv("kernelname", filesv[0], 1); + fp->f_name = strdup(filesv[0]); fp->f_type = strdup(ef.kernel ? elf_kerneltype : elf_moduletype); #ifdef ELF_VERBOSE if (ef.kernel) - printf("%s entry at %p\n", filename, (void *) dest); + printf("%s entry at %p\n", filesv[0], (void *) dest); #else - printf("%s ", filename); + printf("%s ", filesv[0]); #endif fp->f_size = elf_loadimage(fp, &ef, dest); @@ -211,7 +212,7 @@ out: if (ef.firstpage) free(ef.firstpage); - close(ef.fd); + sclose(ef.fd); return(err); } @@ -289,7 +290,7 @@ phdr[i].p_vaddr + off, fpcopy); } if (phdr[i].p_filesz > fpcopy) { - if (lseek(ef->fd, (off_t)(phdr[i].p_offset + fpcopy), + if (slseek(ef->fd, (off_t)(phdr[i].p_offset + fpcopy), SEEK_SET) == -1) { printf("\nelf_loadexec: cannot seek\n"); goto out; @@ -348,11 +349,11 @@ shdr = malloc(chunk); if (shdr == NULL) goto nosyms; - if (lseek(ef->fd, (off_t)ehdr->e_shoff, SEEK_SET) == -1) { + if (slseek(ef->fd, (off_t)ehdr->e_shoff, SEEK_SET) == -1) { printf("\nelf_loadimage: cannot lseek() to section headers"); goto nosyms; } - result = read(ef->fd, shdr, chunk); + result = sread(ef->fd, shdr, chunk); if (result < 0 || (size_t)result != chunk) { printf("\nelf_loadimage: read section headers failed"); goto nosyms; @@ -418,7 +419,7 @@ printf("0x%lx+0x%lx", (long)sizeof(size), size); #endif - if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { + if (slseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { printf("\nelf_loadimage: could not seek for symbols - skipped!"); lastaddr = ssym; ssym = 0; Index: src/sys/boot/common/loader.8 =================================================================== RCS file: /home/ncvs/src/sys/boot/common/loader.8,v retrieving revision 1.40 diff -d -u -r1.40 loader.8 --- src/sys/boot/common/loader.8 21 Feb 2002 05:15:51 -0000 1.40 +++ src/sys/boot/common/loader.8 5 Mar 2002 09:22:06 -0000 @@ -189,11 +189,21 @@ .Pp .It Ic load Xo .Op Fl t Ar type -.Ar file Cm ... +.Op Fl n Ar N +.Ar file1 +.Op Ar ... fileN +.Cm ... .Xc Loads a kernel, kernel loadable module (kld), or a file of opaque contents tagged as being of the type .Ar type . +If +.Fl n +is specified it loads number of files as a single object joining +them together and prompting for user's confirmation when one of +the files could not be found. +This allows loading a large file from a limited-size media (such +as floppy disks) by splitting the file into smaller pieces. Kernel and modules can be either in a.out or elf format. Any arguments passed after the name of the file to be loaded will be passed as arguments to that file. Index: src/sys/boot/common/module.c =================================================================== RCS file: /home/ncvs/src/sys/boot/common/module.c,v retrieving revision 1.22 diff -d -u -r1.22 module.c --- src/sys/boot/common/module.c 16 Nov 2001 21:08:40 -0000 1.22 +++ src/sys/boot/common/module.c 5 Mar 2002 09:22:11 -0000 @@ -38,6 +38,7 @@ #include #include "bootstrap.h" +#include "sread.h" #define MDIR_REMOVED 0x0001 #define MDIR_NOHINTS 0x0002 @@ -50,8 +51,8 @@ STAILQ_ENTRY(moduledir) d_link; }; -static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); -static int file_loadraw(char *type, char *name); +static int file_load(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result); +static int file_loadraw(char *type, int filesc, char *filesv[]); static int file_load_dependencies(struct preloaded_file *base_mod); static char * file_search(const char *name, char **extlist); static struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname, struct mod_depend *verinfo); @@ -79,15 +80,15 @@ /* - * load an object, either a disk file or code module. + * load an object, either a disk file(s) or code module. * * To load a file, the syntax is: * - * load -t + * load -t [-n N] ... * * code modules are loaded as: * - * load + * load [-n N] ... */ COMMAND_SET(load, "load", "load a kernel or module", command_load); @@ -96,9 +97,10 @@ command_load(int argc, char *argv[]) { char *typestr; - int dofile, dokld, ch, error; + int dofile, dokld, ch, error, filesc; dokld = dofile = 0; + filesc = 1; optind = 1; optreset = 1; typestr = NULL; @@ -106,11 +108,14 @@ command_errmsg = "no filename specified"; return(CMD_ERROR); } - while ((ch = getopt(argc, argv, "kt:")) != -1) { + while ((ch = getopt(argc, argv, "kn:t:")) != -1) { switch(ch) { case 'k': dokld = 1; break; + case 'n': + filesc = (int)strtol(optarg, (char **)NULL, 10); + break; case 't': typestr = optarg; dofile = 1; @@ -121,34 +126,38 @@ return(CMD_OK); } } - argv += (optind - 1); - argc -= (optind - 1); + argv += optind; + argc -= optind; + if ((filesc <= 0) || (argc < filesc)) { + command_errmsg = "number of slices is missed or invalid"; + return(CMD_ERROR); + } /* * Request to load a raw file? */ if (dofile) { - if ((argc != 2) || (typestr == NULL) || (*typestr == 0)) { + if ((argc != filesc) || (typestr == NULL) || (*typestr == 0)) { command_errmsg = "invalid load type"; return(CMD_ERROR); } - return(file_loadraw(typestr, argv[1])); + return(file_loadraw(typestr, filesc, argv)); } /* * Do we have explicit KLD load ? */ - if (dokld || file_havepath(argv[1])) { - error = mod_loadkld(argv[1], argc - 2, argv + 2); + if (dokld || file_havepath(argv[0]) || (filesc > 1)) { + error = mod_loadkld(filesc, argv, argc - filesc, argv + filesc); if (error == EEXIST) - sprintf(command_errbuf, "warning: KLD '%s' already loaded", argv[1]); + sprintf(command_errbuf, "warning: KLD '%s' already loaded", argv[0]); return (error == 0 ? CMD_OK : CMD_ERROR); } /* * Looks like a request for a module. */ - error = mod_load(argv[1], NULL, argc - 2, argv + 2); + error = mod_load(filesc, argv, NULL, argc - filesc, argv + filesc); if (error == EEXIST) - sprintf(command_errbuf, "warning: module '%s' already loaded", argv[1]); + sprintf(command_errbuf, "warning: module '%s' already loaded", argv[0]); return (error == 0 ? CMD_OK : CMD_ERROR); } @@ -229,7 +238,7 @@ * File level interface, functions file_* */ int -file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) +file_load(int filesc, char *filesv[], vm_offset_t dest, struct preloaded_file **result) { struct preloaded_file *fp; int error; @@ -237,7 +246,7 @@ error = EFTYPE; for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) { - error = (file_formats[i]->l_load)(filename, loadaddr, &fp); + error = (file_formats[i]->l_load)(filesc, filesv, loadaddr, &fp); if (error == 0) { fp->f_loader = i; /* remember the loader */ *result = fp; @@ -247,7 +256,7 @@ continue; /* Unknown to this handler? */ if (error) { sprintf(command_errbuf, "can't load file '%s': %s", - filename, strerror(error)); + filesv[0], strerror(error)); break; } } @@ -261,6 +270,7 @@ struct mod_depend *verinfo; struct kernel_module *mp; char *dmodname; + char *filesv[1]; int error; md = file_findmetadata(base_file, MODINFOMD_DEPLIST); @@ -272,7 +282,8 @@ dmodname = (char *)(verinfo + 1); if (file_findmodule(NULL, dmodname, verinfo) == NULL) { printf("loading required module '%s'\n", dmodname); - error = mod_load(dmodname, verinfo, 0, NULL); + filesv[0] = dmodname; + error = mod_load(1, filesv, verinfo, 0, NULL); if (error) break; /* @@ -305,7 +316,7 @@ * no arguments or anything. */ int -file_loadraw(char *type, char *name) +file_loadraw(char *type, int filesc, char *filesv[]) { struct preloaded_file *fp; char *cp; @@ -319,16 +330,16 @@ } /* locate the file on the load path */ - cp = file_search(name, NULL); + cp = file_search(filesv[0], NULL); if (cp == NULL) { - sprintf(command_errbuf, "can't find '%s'", name); + sprintf(command_errbuf, "can't find '%s'", filesv[0]); return(CMD_ERROR); } - name = cp; + filesv[0] = cp; - if ((fd = open(name, O_RDONLY)) < 0) { - sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); - free(name); + if ((fd = sopen(filesc, filesv, O_RDONLY)) < 0) { + sprintf(command_errbuf, "can't open '%s': %s", filesv[0], strerror(errno)); + free(filesv[0]); return(CMD_ERROR); } @@ -339,9 +350,9 @@ if (got == 0) /* end of file */ break; if (got < 0) { /* error */ - sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); - free(name); - close(fd); + sprintf(command_errbuf, "error reading '%s': %s", filesv[0], strerror(errno)); + free(filesv[0]); + sclose(fd); return(CMD_ERROR); } laddr += got; @@ -349,7 +360,7 @@ /* Looks OK so far; create & populate control structure */ fp = file_alloc(); - fp->f_name = name; + fp->f_name = filesv[0]; fp->f_type = strdup(type); fp->f_args = NULL; fp->f_metadata = NULL; @@ -362,7 +373,7 @@ /* Add to the list of loaded files */ file_insert_tail(fp); - close(fd); + sclose(fd); return(CMD_OK); } @@ -372,18 +383,18 @@ * If module is already loaded just assign new argc/argv. */ int -mod_load(char *modname, struct mod_depend *verinfo, int argc, char *argv[]) +mod_load(int filesc, char *filesv[], struct mod_depend *verinfo, int argc, char *argv[]) { struct kernel_module *mp; int err; char *filename; - if (file_havepath(modname)) { - printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", modname); - return (mod_loadkld(modname, argc, argv)); + if (file_havepath(filesv[0])) { + printf("Warning: mod_load() called instead of mod_loadkld() for module '%s'\n", filesv[0]); + return (mod_loadkld(filesc, filesv, argc, argv)); } /* see if module is already loaded */ - mp = file_findmodule(NULL, modname, verinfo); + mp = file_findmodule(NULL, filesv[0], verinfo); if (mp) { #ifdef moduleargs if (mp->m_args) @@ -394,12 +405,12 @@ return (0); } /* locate file with the module on the search path */ - filename = mod_searchmodule(modname, verinfo); + filename = mod_searchmodule(filesv[0], verinfo); if (filename == NULL) { - sprintf(command_errbuf, "can't find '%s'", modname); + sprintf(command_errbuf, "can't find '%s'", filesv[0]); return (ENOENT); } - err = mod_loadkld(filename, argc, argv); + err = mod_loadkld(filesc, filesv, argc, argv); return (err); } @@ -408,7 +419,7 @@ * search path. */ int -mod_loadkld(const char *kldname, int argc, char *argv[]) +mod_loadkld(int filesc, char *filesv[], int argc, char *argv[]) { struct preloaded_file *fp, *last_file; int err; @@ -417,9 +428,9 @@ /* * Get fully qualified KLD name */ - filename = file_search(kldname, kld_ext_list); + filename = file_search(filesv[0], kld_ext_list); if (filename == NULL) { - sprintf(command_errbuf, "can't find '%s'", kldname); + sprintf(command_errbuf, "can't find '%s'", filesv[0]); return (ENOENT); } /* @@ -437,7 +448,8 @@ ; do { - err = file_load(filename, loadaddr, &fp); + filesv[0] = filename; + err = file_load(filesc, filesv, loadaddr, &fp); if (err) break; fp->f_args = unargv(argc, argv); Index: src/sys/boot/common/sread.c =================================================================== RCS file: src/sys/boot/common/sread.c diff -N src/sys/boot/common/sread.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/sys/boot/common/sread.c 5 Mar 2002 09:22:11 -0000 @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2002 Maxim Sobolev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * sfiles.c - API for reading sequence of files as if they were a single big + * file. Modeled after standard open()/read()/lseek()/close(). + * Useful for bootstraping a system from a limited-size media, such + * as floppy disks, when one of the files required for + * bootstrapping doesn't fit onto the single media. + * + * API is backward-compatible with file descriptors created using + * ordinary open() - they could with used with s-functions without + * any problems. Please note, however, that the descriptors opened + * with sopen() can't be used with non s-functions. + * + * Please note that for obvious reasons slseek() doesn't support + * SEEK_END and seeking backwards is limited to one slice only. + */ + +#include + +#define NTRIES (3) +#define SLSEEK_BUF (512) + +struct sfiles { + char **filesv; /* Filenames */ + int filesc; /* Number of files */ + int mode; /* sopen() mode */ + int curfile; /* Current file number */ + off_t cur_pos; /* Current offset from the beginning of the sequence */ + off_t file_pos; /* Current offset from the beginning of the slice */ +}; + +int +sopen(int filesc, char *const filesv[], int mode) +{ + int i, fd; + struct sfiles *sfiles; + + if ((fd = open(filesv[0], mode)) == -1) + return (-1); + + /* + * Don't need any extra processing if there is only one file. In this case + * files[fd].f_udata is NULL (ensured by the open()). + */ + if (filesc == 1) + return (fd); + + /* Create and populate sfiles instance */ + sfiles = malloc(sizeof(*sfiles)); + sfiles->filesv = malloc(filesc * sizeof(char *)); + for (i = 0; i < filesc; i++) + sfiles->filesv[i] = strdup(filesv[i]); + sfiles->filesc = filesc; + sfiles->mode = mode; + sfiles->curfile = 0; + sfiles->cur_pos = 0; + sfiles->file_pos = 0; + + (struct sfiles *)files[fd].f_udata = sfiles; + + return (fd); +} + +int +sclose(int fd) +{ + int i; + struct sfiles *sfiles; + + sfiles = (struct sfiles *)files[fd].f_udata; + if (sfiles != NULL) { + /* Destroy sfiles instance */ + for (i = 0; i < sfiles->filesc; i++) + free(sfiles->filesv[i]); + free(sfiles->filesv); + free(sfiles); + files[fd].f_udata = NULL; + } + + return (close(fd)); +} + +int +sread(int fd, void *buf, size_t nbytes) +{ + int i, fd1, nread, totread; + struct sfiles *sfiles; + struct open_file tmp; + + sfiles = (struct sfiles *)files[fd].f_udata; + if (sfiles == NULL) + return (read(fd, buf, nbytes)); + totread = 0; + do { + nread = read(fd, buf, nbytes - totread); + + /* Error */ + if (nread == -1) + return (-1); + + sfiles->cur_pos += nread; + sfiles->file_pos += nread; + totread += nread; + buf += nread; + + /* EOF */ + if ((nread == 0) || (nread < (nbytes - totread))) { + /* Last slice? */ + if (sfiles->curfile == (sfiles->filesc - 1)) + return (nread); + /* Close previous slice */ + if (close(fd) != 0) + return (-1); + sfiles->curfile++; + for (i = 0;; i++) { + fd1 = open(sfiles->filesv[sfiles->curfile], sfiles->mode); + if (fd1 >= 0) + break; + if ((fd1 == -1 && errno != ENOENT) || i == NTRIES) + return (-1); + printf("\nInsert media that contains `%s' and press any key...", \ + sfiles->filesv[sfiles->curfile]); + getchar();putchar('\n'); + } + (struct sfiles *)files[fd1].f_udata = sfiles; + sfiles->file_pos = 0; + if (fd1 != fd) { + tmp = files[fd]; + files[fd] = files[fd1]; + files[fd1] = tmp; + } + } + } while (totread < nbytes); + + return (totread); +} + +off_t +slseek(int fd, off_t offset, int where) +{ + int nread; + struct sfiles *sfiles; + off_t new_pos, seek_by; + + sfiles = (struct sfiles *)files[fd].f_udata; + if (sfiles == NULL) + return (lseek(fd, offset, where)); + + seek_by = 0; + switch (where) { + case SEEK_SET: + seek_by = offset - sfiles->cur_pos; + break; + + case SEEK_CUR: + seek_by = offset; + break; + + case SEEK_END: + panic("slseek(): SEEK_END not supported"); + break; + } + + if (seek_by > 0) { + /* + * Seek forward - implemented using sread(), because otherwise we'll be + * unable to detect that we have crossed slice boundary and hence unable + * to do a long seek crossing that boundary. + */ + void *tmp; + + tmp = malloc(SLSEEK_BUF); + if (tmp == NULL) + return (-1); + + nread = 0; + for (; seek_by > 0; seek_by -= nread) { + nread = sread(fd, tmp, min(seek_by, SLSEEK_BUF)); + if (nread <= 0) + /* Error or EOF */ + break; + } + free(tmp); + if (nread == -1) + return (-1); + } + + if (seek_by != 0) { + /* Seek backward or seek past the boundary of the last slice */ + if (sfiles->file_pos + seek_by < 0) + panic("slseek(): can't seek past the beginning of the slice"); + new_pos = lseek(fd, seek_by, SEEK_CUR); + if (new_pos < 0) + return (-1); + sfiles->cur_pos += new_pos - sfiles->file_pos; + sfiles->file_pos = new_pos; + } + + return (sfiles->cur_pos); +} Index: src/sys/boot/common/sread.h =================================================================== RCS file: src/sys/boot/common/sread.h diff -N src/sys/boot/common/sread.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/sys/boot/common/sread.h 5 Mar 2002 09:22:11 -0000 @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2002 Maxim Sobolev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +extern int sopen(int, char * const *, int); +extern int sclose(int); +extern int sread(int, void *, size_t); +extern off_t slseek(int, off_t, int); Index: src/sys/boot/efi/libefi/copy.c =================================================================== RCS file: /home/ncvs/src/sys/boot/efi/libefi/copy.c,v retrieving revision 1.3 diff -d -u -r1.3 copy.c --- src/sys/boot/efi/libefi/copy.c 14 Sep 2001 08:26:00 -0000 1.3 +++ src/sys/boot/efi/libefi/copy.c 5 Mar 2002 09:22:11 -0000 @@ -38,6 +38,8 @@ #include #include +#include "sread.h" + int efi_copyin(void *src, vm_offset_t dest, size_t len) { @@ -65,5 +67,5 @@ BS->AllocatePages(AllocateAddress, EfiRuntimeServicesData, len >> 12, &p); #endif - return (read(fd, (void*) p, len)); + return (sread(fd, (void*) p, len)); } Index: src/sys/boot/i386/libi386/i386_copy.c =================================================================== RCS file: /home/ncvs/src/sys/boot/i386/libi386/i386_copy.c,v retrieving revision 1.9 diff -d -u -r1.9 i386_copy.c --- src/sys/boot/i386/libi386/i386_copy.c 3 Aug 2000 09:14:01 -0000 1.9 +++ src/sys/boot/i386/libi386/i386_copy.c 5 Mar 2002 09:22:11 -0000 @@ -35,6 +35,7 @@ #include "libi386.h" #include "btxv86.h" +#include "sread.h" #define READIN_BUF (16 * 1024) @@ -80,7 +81,7 @@ for (resid = len; resid > 0; resid -= got, dest += got) { get = min(chunk, resid); - got = read(fd, buf, get); + got = sread(fd, buf, get); if (got <= 0) break; bcopy(buf, PTOV(dest), (size_t)got); Index: src/sys/boot/i386/libi386/i386_module.c =================================================================== RCS file: /home/ncvs/src/sys/boot/i386/libi386/i386_module.c,v retrieving revision 1.5 diff -d -u -r1.5 i386_module.c --- src/sys/boot/i386/libi386/i386_module.c 11 Sep 2001 01:09:23 -0000 1.5 +++ src/sys/boot/i386/libi386/i386_module.c 5 Mar 2002 09:22:11 -0000 @@ -44,13 +44,14 @@ i386_autoload(void) { int error; + char *filesv[1] = {"acpi"}; /* XXX use PnP to locate stuff here */ /* autoload ACPI support */ /* XXX should be in 4th keyed off acpi_load */ if ((getenv("acpi_load") && !getenv("hint.acpi.0.disable"))) { - error = mod_load("acpi", NULL, 0, NULL); + error = mod_load(1, filesv, NULL, 0, NULL); if (error != 0) printf("ACPI autoload failed - %s\n", strerror(error)); } Index: src/sys/boot/ia64/libski/copy.c =================================================================== RCS file: /home/ncvs/src/sys/boot/ia64/libski/copy.c,v retrieving revision 1.1 diff -d -u -r1.1 copy.c --- src/sys/boot/ia64/libski/copy.c 12 Sep 2001 08:34:26 -0000 1.1 +++ src/sys/boot/ia64/libski/copy.c 5 Mar 2002 09:22:11 -0000 @@ -38,6 +38,8 @@ #include +#include "sread.h" + int ski_copyin(void *src, vm_offset_t dest, size_t len) { @@ -55,5 +57,5 @@ int ski_readin(int fd, vm_offset_t dest, size_t len) { - return (read(fd, (void*) IA64_RR_MASK(dest), len)); + return (sread(fd, (void*) IA64_RR_MASK(dest), len)); } Index: src/sys/boot/ofw/libofw/ofw_copy.c =================================================================== RCS file: /home/ncvs/src/sys/boot/ofw/libofw/ofw_copy.c,v retrieving revision 1.10 diff -d -u -r1.10 ofw_copy.c --- src/sys/boot/ofw/libofw/ofw_copy.c 7 Oct 2001 13:27:27 -0000 1.10 +++ src/sys/boot/ofw/libofw/ofw_copy.c 5 Mar 2002 09:22:11 -0000 @@ -33,6 +33,7 @@ #include #include "libofw.h" +#include "sread.h" #define READIN_BUF (4 * 1024) @@ -69,7 +70,7 @@ for (resid = len; resid > 0; resid -= got, p += got) { get = min(chunk, resid); - got = read(fd, buf, get); + got = sread(fd, buf, get); if (got <= 0) { printf("ofw_readin: read failed\n"); Index: src/sys/boot/sparc64/loader/main.c =================================================================== RCS file: /home/ncvs/src/sys/boot/sparc64/loader/main.c,v retrieving revision 1.6 diff -d -u -r1.6 main.c --- src/sys/boot/sparc64/loader/main.c 1 Mar 2002 06:17:28 -0000 1.6 +++ src/sys/boot/sparc64/loader/main.c 5 Mar 2002 09:22:11 -0000 @@ -37,6 +37,7 @@ #include "bootstrap.h" #include "libofw.h" #include "dev_net.h" +#include "sread.h" enum { HEAPVA = 0x800000, @@ -193,7 +194,7 @@ sparc64_readin(const int fd, vm_offset_t va, const size_t len) { mmu_mapin(va, len); - return read(fd, (void *)va, len); + return sread(fd, (void *)va, len); } static ssize_t --------------C69442EE275E6B52E76568F1-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message