#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/reboot.h>
#include <machine/autoconf.h>
#define DUID_SIZE 8
extern void dumpconf(void);
int parseduid(const char *, u_char *);
int cold = 1;
struct device *bootdv = NULL;
char bootdev[16];
char uboot_rootdev[64];
enum devclass bootdev_class = DV_DULL;
void
cpu_configure(void)
{
(void)splhigh();
softintr_init();
(void)config_rootfound("mainbus", NULL);
unmap_startup();
splinit();
cold = 0;
}
struct devmap {
char *dev;
enum devclass class;
};
enum devclass
findtype(void)
{
static const struct devmap devmap[] = {
{ "wd", DV_DISK },
{ "sd", DV_DISK },
{ "octcf", DV_DISK },
{ "amdcf", DV_DISK },
{ NULL, DV_IFNET }
};
const struct devmap *dp = &devmap[0];
if (strlen(bootdev) < 2)
return DV_DISK;
while (dp->dev) {
if (strncmp(bootdev, dp->dev, strlen(dp->dev)) == 0)
break;
dp++;
}
return dp->class;
}
void
parse_uboot_root(const char *p)
{
const char *base;
size_t len;
if (strlen(uboot_rootdev) != 0)
return;
base = strrchr(p, '/');
if (base != NULL)
p = base + 1;
if (parseduid(p, bootduid) == 0) {
strlcpy(uboot_rootdev, p, sizeof(uboot_rootdev));
bootdev_class = DV_DISK;
return;
}
len = strlen(p);
if (len <= 2 || len >= sizeof bootdev - 1)
return;
strlcpy(bootdev, p, sizeof(bootdev));
strlcpy(uboot_rootdev, p, sizeof(uboot_rootdev));
bootdev_class = findtype();
}
static unsigned int
parsehex(int c)
{
if (c >= 'a')
return c - 'a' + 10;
else
return c - '0';
}
int
parseduid(const char *str, u_char *duid)
{
int i;
for (i = 0; i < DUID_SIZE * 2; i++) {
if (!(str[i] >= '0' && str[i] <= '9') &&
!(str[i] >= 'a' && str[i] <= 'f'))
return -1;
}
if (str[DUID_SIZE * 2] != '\0')
return -1;
for (i = 0; i < DUID_SIZE; i++) {
duid[i] = parsehex(str[i * 2]) * 0x10 +
parsehex(str[i * 2 + 1]);
}
return 0;
}
void
diskconf(void)
{
if (bootdv != NULL)
printf("boot device: %s\n", bootdv->dv_xname);
setroot(bootdv, 0, RB_USERREQ);
dumpconf();
}
void
device_register(struct device *dev, void *aux)
{
if (bootdv != NULL || dev->dv_class != bootdev_class)
return;
switch (bootdev_class) {
case DV_DISK:
case DV_IFNET:
if (strcmp(dev->dv_xname, bootdev) == 0)
bootdv = dev;
break;
default:
break;
}
}
const struct nam2blk nam2blk[] = {
{ "sd", 0 },
{ "vnd", 2 },
{ "cd", 3 },
{ "wd", 4 },
{ "rd", 8 },
{ "octcf", 15 },
{ "amdcf", 19 },
{ NULL, -1 }
};