x86 efiboot: pass a filename to BOOTP and parse a DHCP server provided filename.
This commit is contained in:
parent
067319d1de
commit
fcd0bf31a0
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: boot.c,v 1.16 2019/09/13 02:19:45 manu Exp $ */
|
||||
/* $NetBSD: boot.c,v 1.17 2019/09/26 12:21:03 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
|
||||
|
@ -111,6 +111,7 @@ const struct bootblk_command commands[] = {
|
|||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static char *default_fsname;
|
||||
static char *default_devname;
|
||||
static int default_unit, default_partition;
|
||||
static const char *default_filename;
|
||||
|
@ -125,8 +126,11 @@ parsebootfile(const char *fname, char **fsname, char **devname, int *unit,
|
|||
{
|
||||
const char *col;
|
||||
static char savedevname[MAXDEVNAME+1];
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
const struct netboot_fstab *nf;
|
||||
#endif
|
||||
|
||||
*fsname = "ufs";
|
||||
*fsname = default_fsname;
|
||||
if (default_part_name == NULL) {
|
||||
*devname = default_devname;
|
||||
} else {
|
||||
|
@ -152,6 +156,7 @@ parsebootfile(const char *fname, char **fsname, char **devname, int *unit,
|
|||
|
||||
if (strstr(fname, "NAME=") == fname) {
|
||||
strlcpy(savedevname, fname, devlen + 1);
|
||||
*fsname = "ufs";
|
||||
*devname = savedevname;
|
||||
*unit = -1;
|
||||
*partition = -1;
|
||||
|
@ -188,6 +193,13 @@ parsebootfile(const char *fname, char **fsname, char **devname, int *unit,
|
|||
if (i != devlen)
|
||||
return ENXIO;
|
||||
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
nf = netboot_fstab_find(savedevname);
|
||||
if (nf != NULL)
|
||||
*fsname = (char *)nf->name;
|
||||
else
|
||||
#endif
|
||||
*fsname = "ufs";
|
||||
*devname = savedevname;
|
||||
*unit = u;
|
||||
*partition = p;
|
||||
|
@ -278,6 +290,9 @@ boot(void)
|
|||
{
|
||||
int currname;
|
||||
int c;
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
const struct netboot_fstab *nf;
|
||||
#endif
|
||||
|
||||
boot_modules_enabled = !(boot_params.bp_flags & X86_BP_FLAGS_NOMODULES);
|
||||
|
||||
|
@ -288,6 +303,14 @@ boot(void)
|
|||
/* if the user types "boot" without filename */
|
||||
default_filename = DEFFILENAME;
|
||||
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
nf = netboot_fstab_find(default_devname);
|
||||
if (nf != NULL)
|
||||
default_fsname = (char *)nf->name;
|
||||
else
|
||||
#endif
|
||||
default_fsname = "ufs";
|
||||
|
||||
if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
|
||||
#ifdef EFIBOOTCFG_FILENAME
|
||||
int rv = EINVAL;
|
||||
|
@ -456,7 +479,7 @@ command_dev(char *arg)
|
|||
{
|
||||
static char savedevname[MAXDEVNAME + 1];
|
||||
char buf[80];
|
||||
char *fsname, *devname;
|
||||
char *devname;
|
||||
const char *file; /* dummy */
|
||||
|
||||
if (*arg == '\0') {
|
||||
|
@ -474,7 +497,7 @@ command_dev(char *arg)
|
|||
}
|
||||
|
||||
if (strchr(arg, ':') == NULL ||
|
||||
parsebootfile(arg, &fsname, &devname, &default_unit,
|
||||
parsebootfile(arg, &default_fsname, &devname, &default_unit,
|
||||
&default_partition, &file)) {
|
||||
command_help(NULL);
|
||||
return;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: conf.c,v 1.2 2018/04/11 10:32:09 nonaka Exp $ */
|
||||
/* $NetBSD: conf.c,v 1.3 2019/09/26 12:21:03 nonaka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997
|
||||
|
@ -54,20 +54,23 @@
|
|||
#endif
|
||||
#endif
|
||||
#include <biosdisk.h>
|
||||
#include "devopen.h"
|
||||
#include "efinet.h"
|
||||
|
||||
struct devsw devsw[] = {
|
||||
{ "disk", biosdisk_strategy, biosdisk_open, biosdisk_close, biosdisk_ioctl },
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
{ "net", net_strategy, net_open, net_close, net_ioctl },
|
||||
#endif
|
||||
};
|
||||
int ndevs = __arraycount(devsw);
|
||||
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
struct netif_driver *netif_drivers[] = {
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
&efinetif,
|
||||
#endif
|
||||
};
|
||||
int n_netif_drivers = __arraycount(netif_drivers);
|
||||
#endif
|
||||
|
||||
struct fs_ops file_system[] = {
|
||||
#ifdef SUPPORT_CD9660
|
||||
|
@ -113,3 +116,15 @@ struct fs_ops file_system_nfs = FS_OPS(nfs);
|
|||
#ifdef SUPPORT_TFTP
|
||||
struct fs_ops file_system_tftp = FS_OPS(tftp);
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
const struct netboot_fstab netboot_fstab[] = {
|
||||
#ifdef SUPPORT_NFS
|
||||
{ "nfs", &file_system_nfs },
|
||||
#endif
|
||||
#ifdef SUPPORT_TFTP
|
||||
{ "tftp", &file_system_tftp },
|
||||
#endif
|
||||
};
|
||||
const int nnetboot_fstab = __arraycount(netboot_fstab);
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: dev_net.c,v 1.2 2019/07/26 11:30:31 nonaka Exp $ */
|
||||
/* $NetBSD: dev_net.c,v 1.3 2019/09/26 12:21:03 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
|
@ -76,23 +76,23 @@ int
|
|||
net_open(struct open_file *f, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *devname; /* Device part of file name (or NULL). */
|
||||
struct devdesc *dev;
|
||||
int error = 0;
|
||||
|
||||
va_start(ap, f);
|
||||
devname = va_arg(ap, char *);
|
||||
dev = va_arg(ap, struct devdesc *);
|
||||
va_end(ap);
|
||||
|
||||
#ifdef NETIF_DEBUG
|
||||
if (debug)
|
||||
printf("%s\n", devname);
|
||||
printf("%s\n", dev->devname);
|
||||
#endif
|
||||
|
||||
/* On first open, do netif open, mount, etc. */
|
||||
if (netdev_opens == 0) {
|
||||
/* Find network interface. */
|
||||
if (netdev_sock < 0) {
|
||||
netdev_sock = netif_open(devname);
|
||||
netdev_sock = netif_open(dev);
|
||||
if (netdev_sock < 0) {
|
||||
printf("netif_open() failed\n");
|
||||
return ENXIO;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: devopen.c,v 1.7 2019/09/02 06:10:24 manu Exp $ */
|
||||
/* $NetBSD: devopen.c,v 1.8 2019/09/26 12:21:03 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005 The NetBSD Foundation, Inc.
|
||||
|
@ -57,6 +57,7 @@
|
|||
#include "efiboot.h"
|
||||
|
||||
#include <lib/libsa/dev_net.h>
|
||||
#include <lib/libsa/net.h>
|
||||
|
||||
#include <biosdisk.h>
|
||||
#include "devopen.h"
|
||||
|
@ -106,6 +107,40 @@ bios2dev(int biosdev, daddr_t sector, char **devname, int *unit,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
const struct netboot_fstab *
|
||||
netboot_fstab_find(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strcmp(name, "net") == 0)
|
||||
return &netboot_fstab[0];
|
||||
|
||||
for (i = 0; i < nnetboot_fstab; i++) {
|
||||
if (strcmp(name, netboot_fstab[i].name) == 0)
|
||||
return &netboot_fstab[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct netboot_fstab *
|
||||
netboot_fstab_findn(const char *name, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (strncmp(name, "net", len) == 0)
|
||||
return &netboot_fstab[0];
|
||||
|
||||
for (i = 0; i < nnetboot_fstab; i++) {
|
||||
if (strncmp(name, netboot_fstab[i].name, len) == 0)
|
||||
return &netboot_fstab[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct btinfo_bootpath bibp;
|
||||
extern bool kernel_loaded;
|
||||
|
||||
|
@ -115,28 +150,27 @@ extern bool kernel_loaded;
|
|||
int
|
||||
devopen(struct open_file *f, const char *fname, char **file)
|
||||
{
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
static const char *net_devnames[] = {
|
||||
#if defined(SUPPORT_NFS)
|
||||
"nfs",
|
||||
#endif
|
||||
#if defined(SUPPORT_TFTP)
|
||||
"tftp",
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
struct devdesc desc;
|
||||
struct devsw *dev;
|
||||
char *fsname, *devname;
|
||||
int unit, partition;
|
||||
int biosdev;
|
||||
int i, n, error;
|
||||
int i, error;
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
struct devdesc desc;
|
||||
const struct netboot_fstab *nf;
|
||||
char *filename;
|
||||
size_t fsnamelen;
|
||||
int n;
|
||||
#endif
|
||||
|
||||
error = parsebootfile(fname, &fsname, &devname, &unit, &partition,
|
||||
(const char **) file);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
memcpy(file_system, file_system_disk,
|
||||
sizeof(struct fs_ops) * nfsys_disk);
|
||||
nfsys = nfsys_disk;
|
||||
|
||||
/* Search by GPT label or raidframe name */
|
||||
if ((strstr(devname, "NAME=") == devname) ||
|
||||
(strstr(devname, "raid") == devname)) {
|
||||
|
@ -151,64 +185,99 @@ devopen(struct open_file *f, const char *fname, char **file)
|
|||
return error;
|
||||
}
|
||||
|
||||
memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys);
|
||||
nfsys = nfsys_disk;
|
||||
|
||||
/*
|
||||
* Network
|
||||
*/
|
||||
#if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
|
||||
for (i = 0; i < __arraycount(net_devnames); i++) {
|
||||
if (strcmp(devname, net_devnames[i]) == 0) {
|
||||
fsname = devname;
|
||||
devname = "net";
|
||||
break;
|
||||
nf = netboot_fstab_find(devname);
|
||||
if (nf != NULL) {
|
||||
n = 0;
|
||||
if (strcmp(devname, "net") == 0) {
|
||||
for (i = 0; i < nnetboot_fstab; i++) {
|
||||
memcpy(&file_system[n++], netboot_fstab[i].ops,
|
||||
sizeof(struct fs_ops));
|
||||
}
|
||||
} else {
|
||||
memcpy(&file_system[n++], nf->ops,
|
||||
sizeof(struct fs_ops));
|
||||
}
|
||||
}
|
||||
nfsys = n;
|
||||
|
||||
#ifdef SUPPORT_BOOTP
|
||||
try_bootp = 1;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < ndevs; i++) {
|
||||
dev = &devsw[i];
|
||||
if (strcmp(devname, DEV_NAME(dev)) == 0) {
|
||||
if (strcmp(devname, "net") == 0) {
|
||||
n = 0;
|
||||
#if defined(SUPPORT_NFS)
|
||||
if (strcmp(fsname, "nfs") == 0) {
|
||||
memcpy(&file_system[n++], &file_system_nfs,
|
||||
sizeof(file_system_nfs));
|
||||
} else
|
||||
#endif
|
||||
#if defined(SUPPORT_TFTP)
|
||||
if (strcmp(fsname, "tftp") == 0) {
|
||||
memcpy(&file_system[n++], &file_system_tftp,
|
||||
sizeof(file_system_tftp));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if defined(SUPPORT_NFS)
|
||||
memcpy(&file_system[n++], &file_system_nfs,
|
||||
sizeof(file_system_nfs));
|
||||
#endif
|
||||
#if defined(SUPPORT_TFTP)
|
||||
memcpy(&file_system[n++], &file_system_tftp,
|
||||
sizeof(file_system_tftp));
|
||||
#endif
|
||||
}
|
||||
nfsys = n;
|
||||
/* If we got passed a filename, pass it to the BOOTP server. */
|
||||
if (fname) {
|
||||
filename = strchr(fname, ':');
|
||||
if (filename != NULL)
|
||||
filename++;
|
||||
else
|
||||
filename = (char *)fname;
|
||||
strlcpy(bootfile, filename, sizeof(bootfile));
|
||||
}
|
||||
|
||||
try_bootp = 1;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
strlcpy(desc.d_name, "net", sizeof(desc.d_name));
|
||||
desc.d_unit = unit;
|
||||
|
||||
f->f_dev = &devsw[1]; /* must be net */
|
||||
if (!kernel_loaded) {
|
||||
strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
|
||||
BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
|
||||
}
|
||||
error = DEV_OPEN(f->f_dev)(f, &desc);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If the DHCP server provided a file name:
|
||||
* - If it contains a ":", assume it points to a NetBSD kernel.
|
||||
* - If not, assume that the DHCP server was not able to pass
|
||||
* a separate filename for the kernel. (The name probably was
|
||||
* the same as used to load "efiboot".) Ignore it and use
|
||||
* the default in this case.
|
||||
* So we cater to simple DHCP servers while being able to use
|
||||
* the power of conditional behaviour in modern ones.
|
||||
*/
|
||||
filename = strchr(bootfile, ':');
|
||||
if (filename != NULL) {
|
||||
fname = bootfile;
|
||||
|
||||
fsnamelen = filename - fname;
|
||||
nf = netboot_fstab_findn(fname, fsnamelen);
|
||||
if (nf == NULL ||
|
||||
strncmp(fname, "net", fsnamelen) == 0) {
|
||||
printf("Invalid file system type specified in "
|
||||
"%s\n", fname);
|
||||
error = EINVAL;
|
||||
goto neterr;
|
||||
}
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
strlcpy(desc.d_name, devname, sizeof(desc.d_name));
|
||||
desc.d_unit = unit;
|
||||
|
||||
f->f_dev = dev;
|
||||
if (!kernel_loaded) {
|
||||
strncpy(bibp.bootpath, *file,
|
||||
sizeof(bibp.bootpath));
|
||||
BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
|
||||
}
|
||||
return DEV_OPEN(f->f_dev)(f, &desc);
|
||||
memcpy(file_system, nf->ops, sizeof(struct fs_ops));
|
||||
nfsys = 1;
|
||||
}
|
||||
|
||||
filename = fname ? strchr(fname, ':') : NULL;
|
||||
if (filename != NULL) {
|
||||
filename++;
|
||||
if (*filename == '\0') {
|
||||
printf("No file specified in %s\n", fname);
|
||||
error = EINVAL;
|
||||
goto neterr;
|
||||
}
|
||||
} else
|
||||
filename = (char *)fname;
|
||||
|
||||
*file = filename;
|
||||
return 0;
|
||||
|
||||
neterr:
|
||||
DEV_CLOSE(f->f_dev)(f);
|
||||
f->f_dev = NULL;
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* biosdisk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: devopen.h,v 1.4 2019/08/18 02:18:24 manu Exp $ */
|
||||
/* $NetBSD: devopen.h,v 1.5 2019/09/26 12:21:03 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
|
||||
|
@ -42,3 +42,13 @@ struct devdesc {
|
|||
char d_name[MAXDEVNAME];
|
||||
char d_unit;
|
||||
};
|
||||
|
||||
struct netboot_fstab {
|
||||
const char *name;
|
||||
struct fs_ops *ops;
|
||||
};
|
||||
|
||||
extern const struct netboot_fstab netboot_fstab[];
|
||||
extern const int nnetboot_fstab;
|
||||
|
||||
const struct netboot_fstab *netboot_fstab_find(const char *);
|
||||
|
|
Loading…
Reference in New Issue