2006-12-06 17:25:32 -06:00
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
rdev.c - query/set root device.
|
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Date: Sun, 27 Dec 1992 15:55:31 +0000
|
|
|
|
|
Subject: Re: rdev
|
|
|
|
|
From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
|
|
|
|
|
To: Rik Faith <faith@cs.unc.edu>
|
|
|
|
|
|
|
|
|
|
There are quite a few versions of rdev:
|
|
|
|
|
|
|
|
|
|
- the original rootdev that only printed the current root device, by
|
|
|
|
|
Linus.
|
|
|
|
|
- rdev that does what rootdev did and that also allows you to change
|
|
|
|
|
the root (and swap) device, by me.
|
|
|
|
|
- rdev got renamed to setroot and I think even to rootdev on various
|
|
|
|
|
distributions.
|
|
|
|
|
- Peter MacDonald added video mode and RAM disk setting and included
|
|
|
|
|
this version on SLS, called rdev again. I've attached his rdev.c to
|
|
|
|
|
this mail.
|
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Date: 11 Mar 92 21:37:37 GMT
|
|
|
|
|
Subject: rdev - query/set root device
|
|
|
|
|
From: almesber@nessie.cs.id.ethz.ch (Werner Almesberger)
|
|
|
|
|
Organization: Swiss Federal Institute of Technology (ETH), Zurich, CH
|
|
|
|
|
|
|
|
|
|
With all that socket, X11, disk driver and FS hacking going on, apparently
|
|
|
|
|
nobody has found time to address one of the minor nuisances of life: set-
|
|
|
|
|
ting the root FS device is still somewhat cumbersome. I've written a little
|
|
|
|
|
utility which can read and set the root device in boot images:
|
|
|
|
|
|
|
|
|
|
rdev accepts an optional offset argument, just in case the address should
|
|
|
|
|
ever move from 508. If called without arguments, rdev outputs an mtab line
|
|
|
|
|
for the current root FS, just like /etc/rootdev does.
|
|
|
|
|
|
|
|
|
|
ramsize sets the size of the ramdisk. If size is zero, no ramdisk is used.
|
|
|
|
|
|
|
|
|
|
vidmode sets the default video mode at bootup time. -1 uses default video
|
|
|
|
|
mode, -2 uses menu.
|
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Sun Dec 27 10:42:16 1992: Minor usage changes, faith@cs.unc.edu.
|
|
|
|
|
Tue Mar 30 09:31:52 1993: rdev -Rn to set root readonly flag, sct@dcs.ed.ac.uk
|
|
|
|
|
Wed Jun 22 21:12:29 1994: Applied patches from Dave
|
|
|
|
|
(gentzel@nova.enet.dec.com) to prevent dereferencing
|
|
|
|
|
the NULL pointer, faith@cs.unc.edu
|
2006-12-06 17:25:46 -06:00
|
|
|
|
1999-02-22 Arkadiusz Mi<EFBFBD>kiewicz <misiek@pld.ORG.PL>
|
2006-12-06 17:25:39 -06:00
|
|
|
|
- added Native Language Support
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
|
|
-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
2006-12-06 17:25:34 -06:00
|
|
|
|
#include <stdio.h>
|
2006-12-06 17:25:44 -06:00
|
|
|
|
#include <stdlib.h>
|
2006-12-06 17:25:48 -06:00
|
|
|
|
#include <string.h>
|
2006-12-06 17:25:39 -06:00
|
|
|
|
#include "nls.h"
|
2006-12-06 17:25:34 -06:00
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
|
/* rdev.c - query/set root device. */
|
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
|
static void
|
|
|
|
|
usage(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
|
puts(_("usage: rdev [ -rv ] [ -o OFFSET ] [ IMAGE [ VALUE [ OFFSET ] ] ]"));
|
2006-12-06 17:25:39 -06:00
|
|
|
|
puts(_(" rdev /dev/fd0 (or rdev /linux, etc.) displays the current ROOT device"));
|
|
|
|
|
puts(_(" rdev /dev/fd0 /dev/hda2 sets ROOT to /dev/hda2"));
|
|
|
|
|
puts(_(" rdev -R /dev/fd0 1 set the ROOTFLAGS (readonly status)"));
|
|
|
|
|
puts(_(" rdev -r /dev/fd0 627 set the RAMDISK size"));
|
|
|
|
|
puts(_(" rdev -v /dev/fd0 1 set the bootup VIDEOMODE"));
|
|
|
|
|
puts(_(" rdev -o N ... use the byte offset N"));
|
|
|
|
|
puts(_(" rootflags ... same as rdev -R"));
|
|
|
|
|
puts(_(" ramsize ... same as rdev -r"));
|
|
|
|
|
puts(_(" vidmode ... same as rdev -v"));
|
|
|
|
|
puts(_("Note: video modes are: -3=Ask, -2=Extended, -1=NormalVga, 1=key1, 2=key2,..."));
|
|
|
|
|
puts(_(" use -R 1 to mount root readonly, -R 0 for read/write."));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
|
|
#define DEFAULT_OFFSET 508
|
|
|
|
|
|
|
|
|
|
|
2006-12-06 17:25:44 -06:00
|
|
|
|
static void
|
|
|
|
|
die(char *msg) {
|
|
|
|
|
perror(msg);
|
|
|
|
|
exit(1);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
}
|
|
|
|
|
|
2006-12-06 17:25:44 -06:00
|
|
|
|
/* Earlier rdev fails on /dev/ida/c0d0p1 so we allow for
|
2006-12-06 17:25:48 -06:00
|
|
|
|
recursion in /dev. -- Paul Clements */
|
|
|
|
|
/* In fact devfs needs deep recursion. */
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
|
|
|
|
static int
|
2006-12-06 17:25:48 -06:00
|
|
|
|
find_dev_recursive(char *dirnamebuf, int number) {
|
2006-12-06 17:25:44 -06:00
|
|
|
|
DIR *dp;
|
|
|
|
|
struct dirent *dir;
|
|
|
|
|
struct stat s;
|
|
|
|
|
int dirnamelen = 0;
|
|
|
|
|
|
|
|
|
|
if ((dp = opendir(dirnamebuf)) == NULL)
|
|
|
|
|
die("opendir");
|
|
|
|
|
dirnamelen = strlen(dirnamebuf);
|
|
|
|
|
while ((dir = readdir(dp)) != NULL) {
|
|
|
|
|
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
|
|
|
|
|
continue;
|
|
|
|
|
if (dirnamelen + 1 + strlen(dir->d_name) > PATH_MAX)
|
|
|
|
|
continue;
|
|
|
|
|
dirnamebuf[dirnamelen] = '/';
|
|
|
|
|
strcpy(dirnamebuf+dirnamelen+1, dir->d_name);
|
|
|
|
|
if (lstat(dirnamebuf, &s) < 0)
|
|
|
|
|
continue;
|
|
|
|
|
if ((s.st_mode & S_IFMT) == S_IFBLK && s.st_rdev == number)
|
|
|
|
|
return 1;
|
|
|
|
|
if ((s.st_mode & S_IFMT) == S_IFDIR &&
|
2006-12-06 17:25:48 -06:00
|
|
|
|
find_dev_recursive(dirnamebuf, number))
|
2006-12-06 17:25:44 -06:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
dirnamebuf[dirnamelen] = 0;
|
2006-12-06 17:25:49 -06:00
|
|
|
|
closedir(dp);
|
2006-12-06 17:25:44 -06:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
2006-12-06 17:25:44 -06:00
|
|
|
|
static char *
|
|
|
|
|
find_dev(int number) {
|
|
|
|
|
static char name[PATH_MAX+1];
|
|
|
|
|
|
|
|
|
|
if (!number)
|
|
|
|
|
return "Boot device";
|
|
|
|
|
strcpy(name, "/dev");
|
2006-12-06 17:25:48 -06:00
|
|
|
|
if (find_dev_recursive(name, number))
|
2006-12-06 17:25:44 -06:00
|
|
|
|
return name;
|
|
|
|
|
sprintf(name, "0x%04x", number);
|
|
|
|
|
return name;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
}
|
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
|
/* The enum values are significant, things are stored in this order,
|
|
|
|
|
see bootsect.S */
|
|
|
|
|
enum { RDEV, VIDMODE, RAMSIZE, __swapdev__, __syssize__, ROOTFLAGS };
|
|
|
|
|
char *cmdnames[6] = { "rdev", "vidmode", "ramsize", "",
|
2006-12-06 17:25:32 -06:00
|
|
|
|
"", "rootflags"};
|
2006-12-06 17:25:48 -06:00
|
|
|
|
char *desc[6] = { "Root device", "Video mode", "Ramsize", "",
|
2006-12-06 17:25:32 -06:00
|
|
|
|
"", "Root flags"};
|
|
|
|
|
#define shift(n) argv+=n,argc-=n
|
|
|
|
|
|
2006-12-06 17:25:44 -06:00
|
|
|
|
int
|
|
|
|
|
main(int argc, char **argv) {
|
|
|
|
|
int image, offset, dev_nr, i, newoffset=-1;
|
2006-12-06 17:25:48 -06:00
|
|
|
|
char *ptr;
|
|
|
|
|
unsigned short val, have_val;
|
2006-12-06 17:25:44 -06:00
|
|
|
|
struct stat s;
|
2006-12-06 17:25:48 -06:00
|
|
|
|
int cmd;
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
|
textdomain(PACKAGE);
|
|
|
|
|
|
|
|
|
|
/* use the command name to figure out what we have to do - ugly */
|
|
|
|
|
cmd = RDEV;
|
|
|
|
|
if ((ptr = strrchr(argv[0],'/')) != NULL)
|
|
|
|
|
ptr++;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
else
|
2006-12-06 17:25:44 -06:00
|
|
|
|
ptr = argv[0];
|
2006-12-06 17:25:48 -06:00
|
|
|
|
for (i=0; i<=5; i++) {
|
2006-12-06 17:25:44 -06:00
|
|
|
|
if (!strcmp(ptr,cmdnames[i])) {
|
|
|
|
|
cmd = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-12-06 17:25:48 -06:00
|
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
|
|
|
|
while (argc > 1) {
|
|
|
|
|
if (argv[1][0] != '-')
|
|
|
|
|
break;
|
|
|
|
|
switch (argv[1][1]) {
|
2006-12-06 17:25:32 -06:00
|
|
|
|
case 'R':
|
2006-12-06 17:25:44 -06:00
|
|
|
|
cmd = ROOTFLAGS;
|
|
|
|
|
shift(1);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
break;
|
2006-12-06 17:25:44 -06:00
|
|
|
|
case 'r':
|
|
|
|
|
cmd = RAMSIZE;
|
|
|
|
|
shift(1);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
2006-12-06 17:25:44 -06:00
|
|
|
|
cmd = VIDMODE;
|
|
|
|
|
shift(1);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
2006-12-06 17:25:44 -06:00
|
|
|
|
if (argv[1][2]) {
|
2006-12-06 17:25:48 -06:00
|
|
|
|
newoffset = atoi(argv[1]+2);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
shift(1);
|
|
|
|
|
break;
|
|
|
|
|
} else if (argc > 2) {
|
2006-12-06 17:25:48 -06:00
|
|
|
|
newoffset = atoi(argv[2]);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
shift(2);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Fall through. . . */
|
|
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
}
|
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
|
/* Here the only sensible way of using rdev */
|
|
|
|
|
if (argc == 1) {
|
|
|
|
|
if (cmd == RDEV) {
|
|
|
|
|
if (stat("/",&s) < 0) die("/");
|
|
|
|
|
printf("%s /\n", find_dev(s.st_dev));
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
usage();
|
|
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
|
if (argc > 4)
|
2006-12-06 17:25:44 -06:00
|
|
|
|
usage();
|
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
|
/* Ancient garbage.. */
|
|
|
|
|
offset = DEFAULT_OFFSET-cmd*2;
|
|
|
|
|
if (newoffset >= 0)
|
|
|
|
|
offset = newoffset;
|
|
|
|
|
if (argc == 4)
|
|
|
|
|
offset = atoi(argv[3]);
|
|
|
|
|
|
|
|
|
|
have_val = 0;
|
|
|
|
|
|
|
|
|
|
if (argc >= 3) {
|
|
|
|
|
if (cmd == RDEV) {
|
|
|
|
|
if (isdigit(*argv[2])) {
|
|
|
|
|
/* earlier: specify offset */
|
|
|
|
|
/* now: specify major,minor */
|
|
|
|
|
char *p;
|
|
|
|
|
unsigned int ma,mi;
|
|
|
|
|
if ((p = strchr(argv[2], ',')) == NULL)
|
|
|
|
|
die(_("missing comma"));
|
|
|
|
|
ma = atoi(argv[2]);
|
|
|
|
|
mi = atoi(p+1);
|
|
|
|
|
val = ((ma<<8) | mi);
|
|
|
|
|
} else {
|
|
|
|
|
char *device = argv[2];
|
|
|
|
|
if (stat(device,&s) < 0)
|
|
|
|
|
die(device);
|
|
|
|
|
val = s.st_rdev;
|
2006-12-06 17:25:44 -06:00
|
|
|
|
}
|
2006-12-06 17:25:48 -06:00
|
|
|
|
} else {
|
|
|
|
|
val = atoi(argv[2]);
|
2006-12-06 17:25:44 -06:00
|
|
|
|
}
|
2006-12-06 17:25:48 -06:00
|
|
|
|
have_val = 1;
|
2006-12-06 17:25:44 -06:00
|
|
|
|
}
|
2006-12-06 17:25:48 -06:00
|
|
|
|
|
|
|
|
|
if (have_val) {
|
2006-12-06 17:25:44 -06:00
|
|
|
|
if ((image = open(argv[1],O_WRONLY)) < 0) die(argv[1]);
|
|
|
|
|
if (lseek(image,offset,0) < 0) die("lseek");
|
2006-12-06 17:25:48 -06:00
|
|
|
|
if (write(image,(char *)&val,2) != 2) die(argv[1]);
|
2006-12-06 17:25:44 -06:00
|
|
|
|
if (close(image) < 0) die("close");
|
|
|
|
|
} else {
|
|
|
|
|
if ((image = open(argv[1],O_RDONLY)) < 0) die(argv[1]);
|
|
|
|
|
if (lseek(image,offset,0) < 0) die("lseek");
|
|
|
|
|
dev_nr = 0;
|
|
|
|
|
if (read(image,(char *)&dev_nr,2) != 2) die(argv[1]);
|
|
|
|
|
if (close(image) < 0) die("close");
|
|
|
|
|
fputs(desc[cmd], stdout);
|
2006-12-06 17:25:48 -06:00
|
|
|
|
if (cmd == RDEV)
|
2006-12-06 17:25:44 -06:00
|
|
|
|
printf(" %s\n", find_dev(dev_nr));
|
|
|
|
|
else
|
|
|
|
|
printf(" %d\n", dev_nr);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
}
|