Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 05 Mar 2002 12:00:45 +0200
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        hackers@FreeBSD.org, audit@FreeBSD.org, re@FreeBSD.org
Subject:   Extending loader(8) for loading kerels/modules split across several  disks
Message-ID:  <3C84974D.37F683BD@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
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 <stand.h>
 
 #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 <link.h>
 
 #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 <link.h>
 
 #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 <sys/queue.h>
 
 #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 <type> <path>
+ * load -t <type> [-n N] <path1>...<pathN>
  *
  * code modules are loaded as:
  *
- * load <path> <options>
+ * load [-n N] <path1>...<pathN> <options>
  */
 
 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 <sobomax@FreeBSD.org>
+ * 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 <stand.h>
+
+#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 <sobomax@FreeBSD.org>
+ * 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 <efilib.h>
 #include <machine/ia64_cpu.h>
 
+#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 <machine/ia64_cpu.h>
 
+#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 <stand.h>
 
 #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-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C84974D.37F683BD>