summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libstand/cd9660.c8
-rw-r--r--lib/libstand/ext2fs.c12
-rw-r--r--lib/libstand/nandfs.c2
-rw-r--r--lib/libstand/nfs.c4
-rw-r--r--lib/libstand/read.c2
-rw-r--r--lib/libstand/stand.h3
-rw-r--r--lib/libstand/tftp.c4
-rw-r--r--lib/libstand/twiddle.c21
-rw-r--r--lib/libstand/ufs.c14
-rw-r--r--lib/libstand/write.c2
-rw-r--r--sys/boot/common/console.c29
-rw-r--r--sys/boot/common/loader.88
-rw-r--r--sys/boot/forth/loader.conf1
13 files changed, 81 insertions, 29 deletions
diff --git a/lib/libstand/cd9660.c b/lib/libstand/cd9660.c
index 91a091b..09cc7f8 100644
--- a/lib/libstand/cd9660.c
+++ b/lib/libstand/cd9660.c
@@ -286,7 +286,7 @@ cd9660_open(const char *path, struct open_file *f)
buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);
vd = buf;
for (bno = 16;; bno++) {
- twiddle();
+ twiddle(1);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
ISO_DEFAULT_BLOCK_SIZE, buf, &read);
if (rc)
@@ -319,7 +319,7 @@ cd9660_open(const char *path, struct open_file *f)
while (off < dsize) {
if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) {
- twiddle();
+ twiddle(1);
rc = f->f_dev->dv_strategy
(f->f_devdata, F_READ,
cdb2devb(bno + boff),
@@ -379,7 +379,7 @@ cd9660_open(const char *path, struct open_file *f)
/* Check for Rock Ridge since we didn't in the loop above. */
bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
- twiddle();
+ twiddle(1);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
ISO_DEFAULT_BLOCK_SIZE, buf, &read);
if (rc)
@@ -436,7 +436,7 @@ buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
if (fp->f_buf == (char *)0)
fp->f_buf = malloc(ISO_DEFAULT_BLOCK_SIZE);
- twiddle();
+ twiddle(16);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ,
cdb2devb(blkno), ISO_DEFAULT_BLOCK_SIZE, fp->f_buf, &read);
if (rc)
diff --git a/lib/libstand/ext2fs.c b/lib/libstand/ext2fs.c
index e0afb3e..d0b91e0 100644
--- a/lib/libstand/ext2fs.c
+++ b/lib/libstand/ext2fs.c
@@ -353,7 +353,7 @@ ext2fs_open(const char *upath, struct open_file *f)
/* allocate space and read super block */
fs = (struct ext2fs *)malloc(sizeof(*fs));
fp->f_fs = fs;
- twiddle();
+ twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
EXT2_SBLOCK, EXT2_SBSIZE, (char *)fs, &buf_size);
if (error)
@@ -395,7 +395,7 @@ ext2fs_open(const char *upath, struct open_file *f)
len = blkgrps * fs->fs_bsize;
fp->f_bg = malloc(len);
- twiddle();
+ twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
EXT2_SBLOCK + EXT2_SBSIZE / DEV_BSIZE, len,
(char *)fp->f_bg, &buf_size);
@@ -507,7 +507,7 @@ ext2fs_open(const char *upath, struct open_file *f)
if (error)
goto out;
- twiddle();
+ twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata,
F_READ, fsb_to_db(fs, disk_block),
fs->fs_bsize, buf, &buf_size);
@@ -568,7 +568,7 @@ read_inode(ino_t inumber, struct open_file *f)
* Read inode and save it.
*/
buf = malloc(fs->fs_bsize);
- twiddle();
+ twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
ino_to_db(fs, fp->f_bg, inumber), fs->fs_bsize, buf, &rsize);
if (error)
@@ -665,7 +665,7 @@ block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p)
if (fp->f_blk[level] == (char *)0)
fp->f_blk[level] =
malloc(fs->fs_bsize);
- twiddle();
+ twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsb_to_db(fp->f_fs, ind_block_num), fs->fs_bsize,
fp->f_blk[level], &fp->f_blksize[level]);
@@ -723,7 +723,7 @@ buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
bzero(fp->f_buf, block_size);
fp->f_buf_size = block_size;
} else {
- twiddle();
+ twiddle(4);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsb_to_db(fs, disk_block), block_size,
fp->f_buf, &fp->f_buf_size);
diff --git a/lib/libstand/nandfs.c b/lib/libstand/nandfs.c
index 713dc12..b8c51e3 100644
--- a/lib/libstand/nandfs.c
+++ b/lib/libstand/nandfs.c
@@ -921,7 +921,7 @@ nandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
return (0);
}
- twiddle();
+ twiddle(1);
NANDFS_DEBUG("calling get_map with %jx\n", ind_block_num);
map = nandfs_get_map(fs, node, ind_block_num, phys);
if (map == NULL)
diff --git a/lib/libstand/nfs.c b/lib/libstand/nfs.c
index adb0a11..a0b726c 100644
--- a/lib/libstand/nfs.c
+++ b/lib/libstand/nfs.c
@@ -662,7 +662,7 @@ nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
(int)fp->off);
#endif
while ((int)size > 0) {
- twiddle();
+ twiddle(16);
cc = nfs_readdata(fp, fp->off, (void *)addr, size);
/* XXX maybe should retry on certain errors */
if (cc == -1) {
@@ -1311,7 +1311,7 @@ nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
(int)fp->off);
#endif
while ((int)size > 0) {
- twiddle();
+ twiddle(16);
cc = nfs_readdata(fp, fp->off, (void *)addr, size);
/* XXX maybe should retry on certain errors */
if (cc == -1) {
diff --git a/lib/libstand/read.c b/lib/libstand/read.c
index 4c67dbe..a984dbe 100644
--- a/lib/libstand/read.c
+++ b/lib/libstand/read.c
@@ -77,7 +77,7 @@ read(int fd, void *dest, size_t bcount)
return (-1);
}
if (f->f_flags & F_RAW) {
- twiddle();
+ twiddle(4);
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
btodb(f->f_offset), bcount, dest, &resid);
if (errno)
diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h
index 2808722..ebd248d 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -241,7 +241,8 @@ extern int sprintf(char *buf, const char *cfmt, ...) __printflike(2, 3);
extern int snprintf(char *buf, size_t size, const char *cfmt, ...) __printflike(3, 4);
extern void vsprintf(char *buf, const char *cfmt, __va_list);
-extern void twiddle(void);
+extern void twiddle(u_int callerdiv);
+extern void twiddle_divisor(u_int globaldiv);
extern void ngets(char *, int);
#define gets(x) ngets((x), 0)
diff --git a/lib/libstand/tftp.c b/lib/libstand/tftp.c
index e3983c3..6527c4e 100644
--- a/lib/libstand/tftp.c
+++ b/lib/libstand/tftp.c
@@ -447,14 +447,12 @@ tftp_read(struct open_file *f, void *addr, size_t size,
size_t *resid /* out */)
{
struct tftp_handle *tftpfile;
- static int tc = 0;
tftpfile = (struct tftp_handle *) f->f_fsdata;
while (size > 0) {
int needblock, count;
- if (!(tc++ % 16))
- twiddle();
+ twiddle(32);
needblock = tftpfile->off / tftpfile->tftp_blksize + 1;
diff --git a/lib/libstand/twiddle.c b/lib/libstand/twiddle.c
index e0a4c08..96ebbbe 100644
--- a/lib/libstand/twiddle.c
+++ b/lib/libstand/twiddle.c
@@ -42,11 +42,28 @@ __FBSDID("$FreeBSD$");
/* Extra functions from NetBSD standalone printf.c */
+static u_int globaldiv;
+
void
-twiddle()
+twiddle(u_int callerdiv)
{
- static int pos;
+ static u_int callercnt, globalcnt, pos;
+
+ callercnt++;
+ if (callerdiv > 1 && (callercnt % callerdiv) != 0)
+ return;
+
+ globalcnt++;
+ if (globaldiv > 1 && (globalcnt % globaldiv) != 0)
+ return;
putchar("|/-\\"[pos++ & 3]);
putchar('\b');
}
+
+void
+twiddle_divisor(u_int gdiv)
+{
+
+ globaldiv = gdiv;
+}
diff --git a/lib/libstand/ufs.c b/lib/libstand/ufs.c
index b6f7815..928a1d1 100644
--- a/lib/libstand/ufs.c
+++ b/lib/libstand/ufs.c
@@ -155,7 +155,7 @@ read_inode(inumber, f)
* Read inode and save it.
*/
buf = malloc(fs->fs_bsize);
- twiddle();
+ twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
buf, &rsize);
@@ -265,7 +265,7 @@ block_map(f, file_block, disk_block_p)
if (fp->f_blk[level] == (char *)0)
fp->f_blk[level] =
malloc(fs->fs_bsize);
- twiddle();
+ twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fp->f_fs, ind_block_num),
fs->fs_bsize,
@@ -346,7 +346,7 @@ buf_write_file(f, buf_p, size_p)
if (fp->f_buf == (char *)0)
fp->f_buf = malloc(fs->fs_bsize);
- twiddle();
+ twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, disk_block),
block_size, fp->f_buf, &fp->f_buf_size);
@@ -365,7 +365,7 @@ buf_write_file(f, buf_p, size_p)
* Write the block out to storage.
*/
- twiddle();
+ twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
fsbtodb(fs, disk_block),
block_size, fp->f_buf, &fp->f_buf_size);
@@ -406,7 +406,7 @@ buf_read_file(f, buf_p, size_p)
bzero(fp->f_buf, block_size);
fp->f_buf_size = block_size;
} else {
- twiddle();
+ twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, disk_block),
block_size, fp->f_buf, &fp->f_buf_size);
@@ -515,7 +515,7 @@ ufs_open(upath, f)
/* allocate space and read super block */
fs = malloc(SBLOCKSIZE);
fp->f_fs = fs;
- twiddle();
+ twiddle(1);
/*
* Try reading the superblock in each of its possible locations.
*/
@@ -649,7 +649,7 @@ ufs_open(upath, f)
if (rc)
goto out;
- twiddle();
+ twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata,
F_READ, fsbtodb(fs, disk_block),
fs->fs_bsize, buf, &buf_size);
diff --git a/lib/libstand/write.c b/lib/libstand/write.c
index dccdb8b..9e02f08 100644
--- a/lib/libstand/write.c
+++ b/lib/libstand/write.c
@@ -80,7 +80,7 @@ write(fd, dest, bcount)
return (-1);
}
if (f->f_flags & F_RAW) {
- twiddle();
+ twiddle(4);
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
btodb(f->f_offset), bcount, dest, &resid);
if (errno)
diff --git a/sys/boot/common/console.c b/sys/boot/common/console.c
index 6c1fdab..6656eab 100644
--- a/sys/boot/common/console.c
+++ b/sys/boot/common/console.c
@@ -39,6 +39,7 @@ static int cons_set(struct env_var *ev, int flags, const void *value);
static int cons_find(const char *name);
static int cons_check(const char *string);
static void cons_change(const char *string);
+static int twiddle_set(struct env_var *ev, int flags, const void *value);
/*
* Detect possible console(s) to use. If preferred console(s) have been
@@ -52,6 +53,9 @@ cons_probe(void)
int active;
char *prefconsole;
+ /* We want a callback to install the new value when this var changes. */
+ env_setenv("twiddle_divisor", EV_VOLATILE, "1", twiddle_set, env_nounset);
+
/* Do all console probes */
for (cons = 0; consoles[cons] != NULL; cons++) {
consoles[cons]->c_flags = 0;
@@ -232,3 +236,28 @@ cons_change(const char *string)
free(dup);
}
+
+/*
+ * Change the twiddle divisor.
+ *
+ * The user can set the twiddle_divisor variable to directly control how fast
+ * the progress twiddle spins, useful for folks with slow serial consoles. The
+ * code to monitor changes to the variable and propagate them to the twiddle
+ * routines has to live somewhere. Twiddling is console-related so it's here.
+ */
+static int
+twiddle_set(struct env_var *ev, int flags, const void *value)
+{
+ u_long tdiv;
+ char * eptr;
+
+ tdiv = strtoul(value, &eptr, 0);
+ if (*(const char *)value == 0 || *eptr != 0) {
+ printf("invalid twiddle_divisor '%s'\n", (const char *)value);
+ return (CMD_ERROR);
+ }
+ twiddle_divisor((u_int)tdiv);
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+
+ return(CMD_OK);
+}
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index fe247ac..cac5674 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 1, 2013
+.Dd December 22, 2014
.Dt LOADER 8
.Os
.Sh NAME
@@ -670,6 +670,12 @@ Overrides the compile-time set value of
.Dv TCBHASHSIZE
or the preset default of 512.
Must be a power of 2.
+.It Va twiddle_divisor
+Throttles the output of the `twiddle' I/O progress indicator displayed
+while loading the kernel and modules.
+This is useful on slow serial consoles where the time spent waiting for
+these characters to be written can add up to many seconds.
+The default is 1 (full speed); a value of 2 spins half as fast, and so on.
.It Va vm.kmem_size
Sets the size of kernel memory (bytes).
This overrides the value determined when the kernel was compiled.
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 0e56ecc..8e06029 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -75,6 +75,7 @@ module_path="/boot/modules" # Set the module search path
# the block size is set to 512. If the value
# is out of range ( < 8 || > 9008 ) an error is
# returned.
+#twiddle_divisor="1" # >1 means slow down the progress indicator.
##############################################################
OpenPOWER on IntegriCloud