Change the device path representation in libofw to use the full firmware
path, instead of an internal i386 specific one. Don't try to interpret a disklabel in ofw_disk.c, open the partition's device node directly and let the firmware do it. This fixes booting from a partition other than 'a' on sparc64, which is needed to support more installation methods. No objection: ppc
This commit is contained in:
parent
6f0d017cf4
commit
de0acbf78f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=106738
@ -32,7 +32,6 @@
|
||||
#include "libofw.h"
|
||||
#include "bootstrap.h"
|
||||
|
||||
struct ofw_devdesc currdev; /* our current device */
|
||||
struct arch_switch archsw; /* MI/MD interface boundary */
|
||||
|
||||
extern char end[];
|
||||
@ -123,41 +122,9 @@ main(int (*openfirm)(void *))
|
||||
|
||||
printf("\n");
|
||||
|
||||
switch (ofw_devicetype(bootpath)) {
|
||||
case DEVT_DISK:
|
||||
currdev.d_dev = &ofwdisk;
|
||||
currdev.d_type = DEVT_DISK;
|
||||
strncpy(currdev.d_kind.ofwdisk.path, bootpath, 64);
|
||||
currdev.d_kind.ofwdisk.unit = ofwd_getunit(bootpath);
|
||||
|
||||
if (currdev.d_kind.ofwdisk.unit == -1) {
|
||||
printf("Could not locate boot device.\n");
|
||||
OF_exit();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DEVT_NET:
|
||||
currdev.d_dev = &netdev;
|
||||
currdev.d_type = DEVT_NET;
|
||||
strncpy(currdev.d_kind.netif.path, bootpath, 64);
|
||||
/* XXX Only works when we only look for one net device */
|
||||
currdev.d_kind.netif.unit = 0;
|
||||
|
||||
break;
|
||||
|
||||
case DEVT_NONE:
|
||||
default:
|
||||
printf("\n");
|
||||
printf("Could not establish type of boot device.\n");
|
||||
OF_exit();
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, ofw_fmtdev(&currdev),
|
||||
env_setenv("currdev", EV_VOLATILE, bootpath,
|
||||
ofw_setcurrdev, env_nounset);
|
||||
env_setenv("loaddev", EV_VOLATILE, ofw_fmtdev(&currdev), env_noset,
|
||||
env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset,
|
||||
env_nounset);
|
||||
setenv("LINES", "24", 1); /* optional */
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
LIB= ofw
|
||||
INTERNALLIB= true
|
||||
|
||||
SRCS= devicename.c elf_freebsd.c ofw_console.c ofw_copy.c ofw_devsearch.c \
|
||||
ofw_disk.c ofw_memory.c ofw_module.c ofw_net.c ofw_reboot.c \
|
||||
SRCS= devicename.c elf_freebsd.c ofw_console.c ofw_copy.c ofw_disk.c \
|
||||
ofw_memory.c ofw_module.c ofw_net.c ofw_reboot.c \
|
||||
ofw_time.c openfirm.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <sys/disklabel.h>
|
||||
#include "libofw.h"
|
||||
|
||||
static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
|
||||
static int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
|
||||
|
||||
/*
|
||||
* Point (dev) at an allocated device specifier for the device matching the
|
||||
@ -42,14 +42,13 @@ ofw_getdev(void **vdev, const char *devspec, const char **path)
|
||||
{
|
||||
struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev;
|
||||
int rv;
|
||||
|
||||
|
||||
/*
|
||||
* If it looks like this is just a path and no
|
||||
* device, go with the current device.
|
||||
*/
|
||||
if ((devspec == NULL) ||
|
||||
(devspec[0] == '/') ||
|
||||
(strchr(devspec, ':') == NULL)) {
|
||||
(strchr(devspec, '@') == NULL)) {
|
||||
|
||||
if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
|
||||
(path != NULL))
|
||||
@ -67,110 +66,42 @@ ofw_getdev(void **vdev, const char *devspec, const char **path)
|
||||
* Point (dev) at an allocated device specifier matching the string version
|
||||
* at the beginning of (devspec). Return a pointer to the remaining
|
||||
* text in (path).
|
||||
*
|
||||
* In all cases, the beginning of (devspec) is compared to the names
|
||||
* of known devices in the device switch, and then any following text
|
||||
* is parsed according to the rules applied to the device type.
|
||||
*
|
||||
* For disk-type devices, the syntax is:
|
||||
*
|
||||
* disk<unit>[s<slice>][<partition>]:
|
||||
*
|
||||
*/
|
||||
static int
|
||||
ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
|
||||
{
|
||||
struct ofw_devdesc *idev;
|
||||
struct ofw_devdesc *idev;
|
||||
struct devsw *dv;
|
||||
int i, unit, slice, partition, err;
|
||||
char *cp;
|
||||
const char *np;
|
||||
phandle_t handle;
|
||||
const char *p;
|
||||
const char *s;
|
||||
char name[256];
|
||||
char type[64];
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* minimum length check */
|
||||
if (strlen(devspec) < 2)
|
||||
return(EINVAL);
|
||||
|
||||
/* look for a device that matches */
|
||||
for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
|
||||
if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
|
||||
dv = devsw[i];
|
||||
for (p = s = devspec; *s != '\0'; p = s) {
|
||||
if ((s = strchr(p + 1, '/')) == NULL)
|
||||
s = strchr(p, '\0');
|
||||
len = s - devspec;
|
||||
bcopy(devspec, name, len);
|
||||
name[len] = '\0';
|
||||
if ((handle = OF_finddevice(name)) == -1)
|
||||
break;
|
||||
if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
|
||||
continue;
|
||||
for (i = 0; (dv = devsw[i]) != NULL; i++) {
|
||||
if (strncmp(dv->dv_name, type, strlen(type)) == 0)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return(ENOENT);
|
||||
|
||||
if (dv == NULL)
|
||||
return(ENOENT);
|
||||
found:
|
||||
if (*s != '\0')
|
||||
*path = s;
|
||||
idev = malloc(sizeof(struct ofw_devdesc));
|
||||
err = 0;
|
||||
np = (devspec + strlen(dv->dv_name));
|
||||
|
||||
switch(dv->dv_type) {
|
||||
case DEVT_NONE: /* XXX what to do here? Do we care? */
|
||||
break;
|
||||
|
||||
case DEVT_DISK:
|
||||
unit = -1;
|
||||
slice = -1;
|
||||
partition = -1;
|
||||
if (*np && (*np != ':')) {
|
||||
unit = strtol(np, &cp, 10); /* next comes the unit number */
|
||||
if (cp == np) {
|
||||
err = EUNIT;
|
||||
goto fail;
|
||||
}
|
||||
if (*cp == 's') { /* got a slice number */
|
||||
np = cp + 1;
|
||||
slice = strtol(np, &cp, 10);
|
||||
if (cp == np) {
|
||||
err = ESLICE;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (*cp && (*cp != ':')) {
|
||||
partition = *cp - 'a'; /* get a partition number */
|
||||
if ((partition < 0) || (partition >= MAXPARTITIONS)) {
|
||||
err = EPART;
|
||||
goto fail;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
if (*cp && (*cp != ':')) {
|
||||
err = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
idev->d_kind.ofwdisk.unit = unit;
|
||||
idev->d_kind.ofwdisk.slice = slice;
|
||||
idev->d_kind.ofwdisk.partition = partition;
|
||||
if (path != NULL)
|
||||
*path = (*cp == 0) ? cp : cp + 1;
|
||||
break;
|
||||
|
||||
case DEVT_NET:
|
||||
unit = 0;
|
||||
|
||||
if (*np && (*np != ':')) {
|
||||
unit = strtol(np, &cp, 0); /* get unit number if present */
|
||||
if (cp == np) {
|
||||
err = EUNIT;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (*cp && (*cp != ':')) {
|
||||
err = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
idev->d_kind.netif.unit = unit;
|
||||
if (path != NULL)
|
||||
*path = (*cp == 0) ? cp : cp + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
strcpy(idev->d_path, name);
|
||||
idev->d_dev = dv;
|
||||
idev->d_type = dv->dv_type;
|
||||
if (dev == NULL) {
|
||||
@ -179,81 +110,18 @@ ofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
|
||||
*dev = idev;
|
||||
}
|
||||
return(0);
|
||||
|
||||
fail:
|
||||
free(idev);
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to correctly parse bootpath for currdev. Also, enter the device into
|
||||
* the device array in the case of lazy probing (i.e. on sparc64). This has the
|
||||
* effect that the disk the loader was loaded from will always be the first
|
||||
* in the list, but it saves lots of time.
|
||||
*/
|
||||
int
|
||||
ofw_parseofwdev(struct ofw_devdesc *dev, const char *devspec)
|
||||
{
|
||||
char *cp, *ep;
|
||||
int i;
|
||||
struct devsw *dv;
|
||||
|
||||
#ifdef __sparc64__
|
||||
ofwd_enter_dev(devspec);
|
||||
#endif
|
||||
if ((dev->d_kind.ofwdisk.unit = ofwd_getunit(devspec)) == -1)
|
||||
return EUNIT;
|
||||
if ((cp = strrchr(devspec, ',')) == 0)
|
||||
return EINVAL;
|
||||
cp++;
|
||||
if (*cp != ',')
|
||||
return ESLICE;
|
||||
ep = ++cp;
|
||||
dev->d_kind.ofwdisk.slice = strtol(cp, &cp, 10) + 1;
|
||||
if (cp == ep)
|
||||
return ESLICE;
|
||||
if (*cp != ':')
|
||||
return EPART;
|
||||
dev->d_kind.ofwdisk.partition = *++cp - 'a';
|
||||
}
|
||||
|
||||
char *
|
||||
ofw_fmtdev(void *vdev)
|
||||
{
|
||||
struct ofw_devdesc *dev = (struct ofw_devdesc *)vdev;
|
||||
static char buf[128];
|
||||
char *cp;
|
||||
|
||||
switch(dev->d_type) {
|
||||
case DEVT_NONE:
|
||||
strcpy(buf, "(no device)");
|
||||
break;
|
||||
|
||||
case DEVT_DISK:
|
||||
sprintf(buf, "%s%ds%d%c:", dev->d_dev->dv_name,
|
||||
dev->d_kind.ofwdisk.unit, dev->d_kind.ofwdisk.slice,
|
||||
dev->d_kind.ofwdisk.partition + 'a');
|
||||
break;
|
||||
|
||||
case DEVT_NET:
|
||||
sprintf(buf, "%s%d:", dev->d_dev->dv_name,
|
||||
dev->d_kind.netif.unit);
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
ofw_setcurrdev(struct env_var *ev, int flags, void *value)
|
||||
{
|
||||
struct ofw_devdesc *ncurr;
|
||||
int rv;
|
||||
struct ofw_devdesc *ncurr;
|
||||
int rv;
|
||||
|
||||
if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
|
||||
return rv;
|
||||
if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
|
||||
return rv;
|
||||
|
||||
free(ncurr);
|
||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
||||
return 0;
|
||||
free(ncurr);
|
||||
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,57 +31,22 @@
|
||||
struct ofw_devdesc {
|
||||
struct devsw *d_dev;
|
||||
int d_type;
|
||||
union {
|
||||
struct {
|
||||
phandle_t handle; /* OFW handle */
|
||||
unsigned long partoff; /* sector offset */
|
||||
int unit; /* disk number */
|
||||
char path[64]; /* OFW path */
|
||||
int slice; /* slice# */
|
||||
int partition; /* partition in slice */
|
||||
int bsize; /* block size */
|
||||
} ofwdisk;
|
||||
struct {
|
||||
int unit;
|
||||
char path[64];
|
||||
void *dmabuf;
|
||||
} netif;
|
||||
} d_kind;
|
||||
/*
|
||||
* Keeping this around so I know what came from the NetBSD stuff.
|
||||
* I've made a wild guess as to what goes where, but I have no idea if it's
|
||||
* right.
|
||||
*
|
||||
* void *dmabuf;
|
||||
*/
|
||||
phandle_t d_handle;
|
||||
char d_path[256];
|
||||
};
|
||||
|
||||
#define MAXDEV 31 /* Maximum number of devices. */
|
||||
|
||||
/* Known types. Use the same as alpha for consistancy. */
|
||||
#define DEVT_NONE 0
|
||||
#define DEVT_DISK 1
|
||||
#define DEVT_NET 2
|
||||
|
||||
extern int ofw_getdev(void **vdev, const char *devspec, const char **path);
|
||||
extern char *ofw_fmtdev(void *vdev);
|
||||
extern int ofw_parseofwdev(struct ofw_devdesc *, const char *devspec);
|
||||
extern int ofw_setcurrdev(struct env_var *ev, int flags, void *value);
|
||||
|
||||
extern struct devsw ofwdisk;
|
||||
extern struct netif_driver ofwnet;
|
||||
|
||||
void ofwd_enter_dev(const char *);
|
||||
int ofwn_getunit(const char *);
|
||||
|
||||
ssize_t ofw_copyin(const void *src, vm_offset_t dest, const size_t len);
|
||||
ssize_t ofw_copyout(const vm_offset_t src, void *dest, const size_t len);
|
||||
ssize_t ofw_readin(const int fd, vm_offset_t dest, const size_t len);
|
||||
|
||||
void ofw_devsearch_init(void);
|
||||
int ofw_devsearch(const char *, char *);
|
||||
int ofw_devicetype(char *);
|
||||
|
||||
extern int ofw_boot(void);
|
||||
extern int ofw_autoload(void);
|
||||
|
||||
@ -99,10 +64,10 @@ extern struct file_format ofw_elf;
|
||||
|
||||
extern void reboot(void);
|
||||
|
||||
extern int main(int (*openfirm)(void *));
|
||||
|
||||
struct ofw_reg
|
||||
{
|
||||
cell_t base;
|
||||
cell_t size;
|
||||
};
|
||||
|
||||
extern int (*openfirmware)(void *);
|
||||
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Benno Rice
|
||||
* 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 Benno Rice ``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 TOOLS GMBH 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$
|
||||
*/
|
||||
|
||||
#include <stand.h>
|
||||
|
||||
#include "libofw.h"
|
||||
|
||||
static phandle_t curnode;
|
||||
|
||||
/*
|
||||
* Initialise a device tree search. We do this by setting curpackage to point
|
||||
* to the root node.
|
||||
*/
|
||||
void
|
||||
ofw_devsearch_init(void)
|
||||
{
|
||||
curnode = OF_peer(0);
|
||||
}
|
||||
|
||||
static phandle_t
|
||||
nextnode(phandle_t current)
|
||||
{
|
||||
phandle_t node;
|
||||
|
||||
node = OF_child(current);
|
||||
|
||||
if (node == -1)
|
||||
return(-1);
|
||||
|
||||
if (node == 0) {
|
||||
node = OF_peer(current);
|
||||
|
||||
if (node == -1)
|
||||
return(-1);
|
||||
|
||||
if (node == 0) {
|
||||
phandle_t newnode;
|
||||
|
||||
newnode = current;
|
||||
node = 0;
|
||||
|
||||
while (node == 0) {
|
||||
node = OF_parent(newnode);
|
||||
|
||||
if (node == -1 || node == 0)
|
||||
return ((int)node);
|
||||
|
||||
newnode = node;
|
||||
node = OF_peer(newnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for devices in the device tree with a certain device_type.
|
||||
* Return their paths.
|
||||
*/
|
||||
int
|
||||
ofw_devsearch(const char *type, char *path)
|
||||
{
|
||||
phandle_t new;
|
||||
char str[32];
|
||||
int i;
|
||||
|
||||
for (;;) {
|
||||
new = nextnode(curnode);
|
||||
if (new == 0 || new == -1) {
|
||||
return((int)new);
|
||||
}
|
||||
|
||||
curnode = new;
|
||||
|
||||
if ((i = OF_getprop(curnode, "device_type", str, 31)) != -1) {
|
||||
|
||||
if (strncmp(str, type, 32) == 0) {
|
||||
if ((i = OF_package_to_path(curnode, path, 254)) == -1)
|
||||
return(-1);
|
||||
|
||||
path[i] = '\0';
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the device_type of a node.
|
||||
* Return DEVT_DISK, DEVT_NET or DEVT_NONE.
|
||||
*/
|
||||
int
|
||||
ofw_devicetype(char *path)
|
||||
{
|
||||
phandle_t node;
|
||||
char type[16];
|
||||
|
||||
node = OF_finddevice(path);
|
||||
if (node == -1)
|
||||
return DEVT_NONE;
|
||||
|
||||
OF_getprop(node, "device_type", type, 16);
|
||||
|
||||
if (strncmp(type, "block", 16) == 0)
|
||||
return DEVT_DISK;
|
||||
else if (strncmp(type, "network", 16) == 0)
|
||||
return DEVT_NET;
|
||||
else
|
||||
return DEVT_NONE;
|
||||
}
|
@ -41,147 +41,28 @@
|
||||
#include "bootstrap.h"
|
||||
#include "libofw.h"
|
||||
|
||||
#define DISKSECSZ 512
|
||||
|
||||
static int ofwd_init(void);
|
||||
static int ofwd_strategy(void *devdata, int flag, daddr_t dblk,
|
||||
size_t size, char *buf, size_t *rsize);
|
||||
static int ofwd_open(struct open_file *f, ...);
|
||||
static int ofwd_close(struct open_file *f);
|
||||
static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||
static void ofwd_print(int verbose);
|
||||
static char * ofwd_getdevpath(int unit);
|
||||
int readdisklabel(struct ofw_devdesc *);
|
||||
|
||||
struct devsw ofwdisk = {
|
||||
"disk",
|
||||
"block",
|
||||
DEVT_DISK,
|
||||
ofwd_init,
|
||||
ofwd_strategy,
|
||||
ofwd_open,
|
||||
ofwd_close,
|
||||
noioctl,
|
||||
ofwd_ioctl,
|
||||
ofwd_print
|
||||
};
|
||||
|
||||
static struct ofwdinfo {
|
||||
int ofwd_unit;
|
||||
char ofwd_path[255];
|
||||
} ofwdinfo[MAXDEV];
|
||||
static int nofwdinfo = 0;
|
||||
static int probed;
|
||||
|
||||
#define OFDP_FOUND 0
|
||||
#define OFDP_NOTFOUND 1
|
||||
#define OFDP_TERMINATE 2
|
||||
|
||||
#define MAXDEV_IDE 4
|
||||
#define MAXDEV_DEFAULT 16 /* SCSI etc. */
|
||||
|
||||
void
|
||||
ofwd_enter_dev(const char *devpath)
|
||||
{
|
||||
char *p;
|
||||
int n;
|
||||
|
||||
if (ofwd_getunit(devpath) != -1)
|
||||
return;
|
||||
if ((p = strrchr(devpath, ',')) != NULL)
|
||||
n = p - devpath;
|
||||
else
|
||||
n = strlen(devpath);
|
||||
ofwdinfo[nofwdinfo].ofwd_unit = nofwdinfo;
|
||||
strncpy(ofwdinfo[nofwdinfo].ofwd_path, devpath, n);
|
||||
ofwdinfo[nofwdinfo].ofwd_path[n] = '\0';
|
||||
printf("disk%d is %s\n", nofwdinfo, ofwdinfo[nofwdinfo].ofwd_path);
|
||||
nofwdinfo++;
|
||||
}
|
||||
|
||||
static int
|
||||
ofwd_probe_dev(char *devpath)
|
||||
{
|
||||
ihandle_t instance;
|
||||
int rv;
|
||||
|
||||
/* Is the device already in the list? */
|
||||
if (ofwd_getunit(devpath) != -1)
|
||||
return OFDP_FOUND;
|
||||
instance = OF_open(devpath);
|
||||
if (instance != -1) {
|
||||
ofwd_enter_dev(devpath);
|
||||
OF_close(instance);
|
||||
} else
|
||||
return OFDP_NOTFOUND;
|
||||
if (nofwdinfo > MAXDEV) {
|
||||
printf("Hit MAXDEV probing disks.\n");
|
||||
return OFDP_TERMINATE;
|
||||
}
|
||||
return OFDP_FOUND;
|
||||
}
|
||||
|
||||
static int
|
||||
ofwd_probe_devs(void)
|
||||
{
|
||||
int ret;
|
||||
char devpath[255];
|
||||
#ifdef __sparc64__
|
||||
int i, n;
|
||||
char cdevpath[255];
|
||||
#endif
|
||||
|
||||
probed = 1;
|
||||
ofw_devsearch_init();
|
||||
while ((ret = ofw_devsearch("block", devpath)) != 0) {
|
||||
devpath[sizeof devpath - 1] = 0;
|
||||
if (ret == -1)
|
||||
return 1;
|
||||
#ifdef DEBUG
|
||||
printf("devpath=\"%s\" ret=%d\n", devpath, ret);
|
||||
#endif
|
||||
|
||||
if (strstr(devpath, "cdrom") != 0)
|
||||
continue;
|
||||
|
||||
#ifdef __sparc64__
|
||||
/*
|
||||
* sparc64 machines usually only have a single disk node as
|
||||
* child of the controller (in the ATA case, there may exist
|
||||
* an additional cdrom node, which we ignore above, since
|
||||
* booting from it is special, and it can also be used as a
|
||||
* disk node).
|
||||
* Devices are accessed by using disk@unit; when no unit
|
||||
* number is given, 0 is assumed.
|
||||
* There is no way we can enumerate the existing disks except
|
||||
* trying to open them, which unfortunately creates some deleays
|
||||
* and spurioius warnings printed by the prom, which we can't
|
||||
* do much about. The search may not stop on the first
|
||||
* unsuccessful attempt, because that would cause disks that
|
||||
* follow one with an invalid label (like CD-ROMS) would not
|
||||
* be detected this way.
|
||||
* Try to at least be a bit smart and only probe 4 devices in
|
||||
* the IDE case.
|
||||
*/
|
||||
if (strstr(devpath, "/ide@") != NULL)
|
||||
n = MAXDEV_IDE;
|
||||
else
|
||||
n = MAXDEV_DEFAULT;
|
||||
for (i = 0; i < n; i++) {
|
||||
sprintf(cdevpath, "%s@%d", devpath, i);
|
||||
if (ofwd_probe_dev(cdevpath) == OFDP_TERMINATE)
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
if (ofwd_probe_dev(devpath) == OFDP_TERMINATE)
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ofwd_init(void)
|
||||
{
|
||||
/* Short-circuit the device probing, since it takes too long. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -194,18 +75,14 @@ ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
|
||||
int n;
|
||||
int i, j;
|
||||
|
||||
pos = (dp->d_kind.ofwdisk.partoff + dblk) * dp->d_kind.ofwdisk.bsize;
|
||||
|
||||
pos = dblk * 512;
|
||||
do {
|
||||
if (OF_seek(dp->d_kind.ofwdisk.handle, pos) < 0) {
|
||||
if (OF_seek(dp->d_handle, pos) < 0)
|
||||
return EIO;
|
||||
}
|
||||
n = OF_read(dp->d_kind.ofwdisk.handle, buf, size);
|
||||
if (n < 0 && n != -2) {
|
||||
n = OF_read(dp->d_handle, buf, size);
|
||||
if (n < 0 && n != -2)
|
||||
return EIO;
|
||||
}
|
||||
} while (n == -2);
|
||||
|
||||
*rsize = size;
|
||||
return 0;
|
||||
}
|
||||
@ -213,55 +90,18 @@ ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf,
|
||||
static int
|
||||
ofwd_open(struct open_file *f, ...)
|
||||
{
|
||||
va_list vl;
|
||||
struct ofw_devdesc *dp;
|
||||
char *devpath;
|
||||
phandle_t diskh;
|
||||
char buf[256];
|
||||
int i, j;
|
||||
phandle_t handle;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, f);
|
||||
dp = va_arg(vl, struct ofw_devdesc *);
|
||||
va_end(vl);
|
||||
|
||||
/*
|
||||
* The unit number is really an index into our device array.
|
||||
* If it is not in the list, we may need to probe now.
|
||||
*/
|
||||
if (!probed && dp->d_kind.ofwdisk.unit >= nofwdinfo)
|
||||
ofwd_probe_devs();
|
||||
if (dp->d_kind.ofwdisk.unit >= nofwdinfo)
|
||||
return 1;
|
||||
devpath = ofwdinfo[dp->d_kind.ofwdisk.unit].ofwd_path;
|
||||
sprintf(buf, "%s,%d:%c", devpath, dp->d_kind.ofwdisk.slice,
|
||||
'a' + dp->d_kind.ofwdisk.partition);
|
||||
if ((diskh = OF_open(buf)) == -1) {
|
||||
printf("ofwd_open: Could not open %s\n", buf);
|
||||
if ((handle = OF_open(dp->d_path)) == -1) {
|
||||
printf("ofwd_open: Could not open %s\n", dp->d_path);
|
||||
return 1;
|
||||
}
|
||||
dp->d_kind.ofwdisk.bsize = DISKSECSZ;
|
||||
dp->d_kind.ofwdisk.handle = diskh;
|
||||
readdisklabel(dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
readdisklabel(struct ofw_devdesc *dp)
|
||||
{
|
||||
char buf[DISKSECSZ];
|
||||
struct disklabel *lp;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
dp->d_kind.ofwdisk.partoff = 0;
|
||||
dp->d_dev->dv_strategy(dp, 0, LABELSECTOR, sizeof(buf), buf, &size);
|
||||
i = dp->d_kind.ofwdisk.partition;
|
||||
if (i >= MAXPARTITIONS)
|
||||
return 1;
|
||||
|
||||
lp = (struct disklabel *)(buf + LABELOFFSET);
|
||||
dp->d_kind.ofwdisk.partoff = lp->d_partitions[i].p_offset;
|
||||
dp->d_handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -269,41 +109,19 @@ static int
|
||||
ofwd_close(struct open_file *f)
|
||||
{
|
||||
struct ofw_devdesc *dev = f->f_devdata;
|
||||
OF_close(dev->d_kind.ofwdisk.handle);
|
||||
|
||||
OF_close(dev->d_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ofwd_ioctl(struct open_file *f, u_long cmd, void *data)
|
||||
{
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
ofwd_print(int verbose)
|
||||
{
|
||||
int i;
|
||||
char line[80];
|
||||
|
||||
if (!probed)
|
||||
ofwd_probe_devs();
|
||||
for (i = 0; i < nofwdinfo; i++) {
|
||||
sprintf(line, " disk%d: %s", i, ofwdinfo[i].ofwd_path);
|
||||
pager_output(line);
|
||||
pager_output("\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
ofwd_getunit(const char *path)
|
||||
{
|
||||
char *p;
|
||||
int i, n;
|
||||
|
||||
if ((p = strrchr(path, ',')) != NULL)
|
||||
n = p - path;
|
||||
else
|
||||
n = strlen(path);
|
||||
for (i = 0; i < nofwdinfo; i++) {
|
||||
if (strncmp(path, ofwdinfo[i].ofwd_path, n) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -255,7 +255,6 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
struct preloaded_file *kfp;
|
||||
struct preloaded_file *xp;
|
||||
struct file_metadata *md;
|
||||
struct ofw_devdesc *rootdev;
|
||||
vm_offset_t kernend;
|
||||
vm_offset_t addr;
|
||||
vm_offset_t envp;
|
||||
@ -273,16 +272,10 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
* MI code before launching the kernel.
|
||||
*/
|
||||
rootdevname = getenv("rootdev");
|
||||
ofw_getdev((void **)(&rootdev), rootdevname, NULL);
|
||||
if (rootdev == NULL) { /* bad $rootdev/$currdev */
|
||||
printf("can't determine root device\n");
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
if (rootdevname == NULL)
|
||||
rootdevname = getenv("currdev");
|
||||
/* Try reading the /etc/fstab file to select the root device */
|
||||
getrootmount(ofw_fmtdev((void *)rootdev));
|
||||
|
||||
free(rootdev);
|
||||
getrootmount(rootdevname);
|
||||
|
||||
/* find the last module in the chain */
|
||||
addr = 0;
|
||||
|
@ -255,7 +255,6 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
struct preloaded_file *kfp;
|
||||
struct preloaded_file *xp;
|
||||
struct file_metadata *md;
|
||||
struct ofw_devdesc *rootdev;
|
||||
vm_offset_t kernend;
|
||||
vm_offset_t addr;
|
||||
vm_offset_t envp;
|
||||
@ -273,16 +272,10 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
* MI code before launching the kernel.
|
||||
*/
|
||||
rootdevname = getenv("rootdev");
|
||||
ofw_getdev((void **)(&rootdev), rootdevname, NULL);
|
||||
if (rootdev == NULL) { /* bad $rootdev/$currdev */
|
||||
printf("can't determine root device\n");
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
if (rootdevname == NULL)
|
||||
rootdevname = getenv("currdev");
|
||||
/* Try reading the /etc/fstab file to select the root device */
|
||||
getrootmount(ofw_fmtdev((void *)rootdev));
|
||||
|
||||
free(rootdev);
|
||||
getrootmount(rootdevname);
|
||||
|
||||
/* find the last module in the chain */
|
||||
addr = 0;
|
||||
|
@ -16,6 +16,7 @@ LOADER_CD9660_SUPPORT?= yes
|
||||
LOADER_NET_SUPPORT?= yes
|
||||
LOADER_NFS_SUPPORT?= yes
|
||||
LOADER_TFTP_SUPPORT?= yes
|
||||
LOADER_ZIP_SUPPORT?= yes
|
||||
LOADER_GZIP_SUPPORT?= yes
|
||||
LOADER_BZIP2_SUPPORT?= no
|
||||
|
||||
@ -28,6 +29,9 @@ CFLAGS+= -DLOADER_UFS_SUPPORT
|
||||
.if ${LOADER_CD9660_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_CD9660_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_ZIP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_ZIP_SUPPORT
|
||||
.endif
|
||||
.if ${LOADER_GZIP_SUPPORT} == "yes"
|
||||
CFLAGS+= -DLOADER_GZIP_SUPPORT
|
||||
.endif
|
||||
@ -81,7 +85,7 @@ LIBSTAND= -lstand
|
||||
.endif
|
||||
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
|
||||
|
||||
LDADD= ${LIBFICL} ${LIBSTAND} ${LIBOFW}
|
||||
LDADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND}
|
||||
|
||||
vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
|
||||
sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
|
||||
|
@ -75,7 +75,6 @@ vm_offset_t heapva;
|
||||
phandle_t pmemh; /* OFW memory handle */
|
||||
|
||||
struct memory_slice memslices[18];
|
||||
struct ofw_devdesc bootdev;
|
||||
|
||||
/*
|
||||
* Machine dependent structures that the machine independent
|
||||
@ -368,9 +367,6 @@ main(int (*openfirm)(void *))
|
||||
archsw.arch_copyout = ofw_copyout;
|
||||
archsw.arch_readin = sparc64_readin;
|
||||
archsw.arch_autoload = sparc64_autoload;
|
||||
#ifdef ELF_CRC32
|
||||
archsw.arch_crc32 = sparc64_crc32;
|
||||
#endif
|
||||
|
||||
init_heap();
|
||||
setheap((void *)heapva, (void *)(heapva + HEAPSZ));
|
||||
@ -398,46 +394,32 @@ main(int (*openfirm)(void *))
|
||||
chosenh = OF_finddevice("/chosen");
|
||||
OF_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
|
||||
|
||||
bootdev.d_type = ofw_devicetype(bootpath);
|
||||
switch (bootdev.d_type) {
|
||||
case DEVT_DISK:
|
||||
bootdev.d_dev = &ofwdisk;
|
||||
/*
|
||||
* Sun compatible bootable CD-ROMs have a disk label placed
|
||||
* before the cd9660 data, with the actual filesystem being
|
||||
* in the first partition, while the other partitions contain
|
||||
* pseudo disk labels with embedded boot blocks for different
|
||||
* architectures, which may be followed by UFS filesystems.
|
||||
* The firmware will set the boot path to the partition it
|
||||
* boots from ('f' in the sun4u case), but we want the kernel
|
||||
* to be loaded from the cd9660 fs ('a'), so the boot path
|
||||
* needs to be altered.
|
||||
*/
|
||||
if (strstr(bootpath, "cdrom") != NULL &&
|
||||
bootpath[strlen(bootpath) - 2] == ':') {
|
||||
bootpath[strlen(bootpath) - 1] = 'a';
|
||||
printf("Boot path set to %s\n", bootpath);
|
||||
}
|
||||
strncpy(bootdev.d_kind.ofwdisk.path, bootpath, 64);
|
||||
ofw_parseofwdev(&bootdev, bootpath);
|
||||
break;
|
||||
case DEVT_NET:
|
||||
bootdev.d_dev = &netdev;
|
||||
strncpy(bootdev.d_kind.netif.path, bootpath, 64);
|
||||
bootdev.d_kind.netif.unit = 0;
|
||||
break;
|
||||
/*
|
||||
* Sun compatible bootable CD-ROMs have a disk label placed
|
||||
* before the cd9660 data, with the actual filesystem being
|
||||
* in the first partition, while the other partitions contain
|
||||
* pseudo disk labels with embedded boot blocks for different
|
||||
* architectures, which may be followed by UFS filesystems.
|
||||
* The firmware will set the boot path to the partition it
|
||||
* boots from ('f' in the sun4u case), but we want the kernel
|
||||
* to be loaded from the cd9660 fs ('a'), so the boot path
|
||||
* needs to be altered.
|
||||
*/
|
||||
if (bootpath[strlen(bootpath) - 2] == ':' &&
|
||||
bootpath[strlen(bootpath) - 1] == 'f') {
|
||||
bootpath[strlen(bootpath) - 1] = 'a';
|
||||
printf("Boot path set to %s\n", bootpath);
|
||||
}
|
||||
|
||||
env_setenv("currdev", EV_VOLATILE, ofw_fmtdev(&bootdev),
|
||||
env_setenv("currdev", EV_VOLATILE, bootpath,
|
||||
ofw_setcurrdev, env_nounset);
|
||||
env_setenv("loaddev", EV_VOLATILE, ofw_fmtdev(&bootdev),
|
||||
env_setenv("loaddev", EV_VOLATILE, bootpath,
|
||||
env_noset, env_nounset);
|
||||
|
||||
printf("\n");
|
||||
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
|
||||
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
|
||||
printf("bootpath=\"%s\"\n", bootpath);
|
||||
printf("loaddev=%s\n", getenv("loaddev"));
|
||||
|
||||
/* Give control to the machine independent loader code. */
|
||||
interact();
|
||||
|
@ -261,7 +261,6 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
struct preloaded_file *kfp;
|
||||
struct preloaded_file *xp;
|
||||
struct file_metadata *md;
|
||||
struct ofw_devdesc *rootdev;
|
||||
vm_offset_t kernend;
|
||||
vm_offset_t addr;
|
||||
vm_offset_t envp;
|
||||
@ -276,17 +275,9 @@ md_load(char *args, vm_offset_t *modulep)
|
||||
* This should perhaps go to MI code and/or have $rootdev tested/set by
|
||||
* MI code before launching the kernel.
|
||||
*/
|
||||
rootdevname = getenv("rootdev");
|
||||
ofw_getdev((void **)(&rootdev), rootdevname, NULL);
|
||||
if (rootdev == NULL) { /* bad $rootdev/$currdev */
|
||||
printf("can't determine root device\n");
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
/* Try reading the /etc/fstab file to select the root device */
|
||||
getrootmount(ofw_fmtdev((void *)rootdev));
|
||||
|
||||
free(rootdev);
|
||||
if ((rootdevname = getenv("rootdev")) == NULL)
|
||||
rootdevname = getenv("currdev");
|
||||
getrootmount(rootdevname);
|
||||
|
||||
/* find the last module in the chain */
|
||||
addr = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user