bhyve: add varfile option to nvlist of lpc device
Use seperate nvlist entries for the romfile and the varfile. While here, don't leak varfd in bootrom_loadrom(). Reviewed by: jhb, markj Differential Revision: https://reviews.freebsd.org/D33433
This commit is contained in:
parent
f266082f11
commit
87f6367f10
@ -23,7 +23,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd September 25, 2021
|
||||
.Dd March 2, 2022
|
||||
.Dt BHYVE_CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -448,6 +448,11 @@ The contents of this file are copied into the guest's
|
||||
memory ending just before the 4GB physical address.
|
||||
If a boot ROM is present, a firmware interface device is
|
||||
also enabled for use by the boot ROM.
|
||||
.It Va bootvars Ta path Ta Ta
|
||||
Path to boot VARS.
|
||||
The contents of this file are copied beneath the boot ROM.
|
||||
Firmware can write to it to save variables.
|
||||
All variables will be persistent even on reboots of the guest.
|
||||
.It Va com1 Ta node Ta Ta
|
||||
Settings for the COM1 serial port device.
|
||||
.It Va com2 Ta node Ta Ta
|
||||
|
@ -191,19 +191,33 @@ bootrom_alloc(struct vmctx *ctx, size_t len, int prot, int flags,
|
||||
}
|
||||
|
||||
int
|
||||
bootrom_loadrom(struct vmctx *ctx, const char *romfile)
|
||||
bootrom_loadrom(struct vmctx *ctx, const nvlist_t *nvl)
|
||||
{
|
||||
struct stat sbuf;
|
||||
ssize_t rlen;
|
||||
off_t rom_size, var_size, total_size;
|
||||
char *ptr, *varfile;
|
||||
char *ptr, *romfile;
|
||||
int fd, varfd, i, rv;
|
||||
const char *bootrom, *varfile;
|
||||
|
||||
rv = -1;
|
||||
varfd = -1;
|
||||
|
||||
varfile = strdup(romfile);
|
||||
romfile = strsep(&varfile, ",");
|
||||
bootrom = get_config_value_node(nvl, "bootrom");
|
||||
if (bootrom == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_config_value_node may use a thread local buffer to return
|
||||
* variables. So, when we query the second variable, the first variable
|
||||
* might get overwritten. For that reason, the bootrom should be
|
||||
* duplicated.
|
||||
*/
|
||||
romfile = strdup(bootrom);
|
||||
if (romfile == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fd = open(romfile, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@ -212,6 +226,16 @@ bootrom_loadrom(struct vmctx *ctx, const char *romfile)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (fstat(fd, &sbuf) < 0) {
|
||||
EPRINTLN("Could not fstat bootrom file \"%s\": %s", romfile,
|
||||
strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
rom_size = sbuf.st_size;
|
||||
|
||||
varfile = get_config_value_node(nvl, "bootvars");
|
||||
var_size = 0;
|
||||
if (varfile != NULL) {
|
||||
varfd = open(varfile, O_RDWR);
|
||||
if (varfd < 0) {
|
||||
@ -219,23 +243,14 @@ bootrom_loadrom(struct vmctx *ctx, const char *romfile)
|
||||
"\"%s\": %s\n", varfile, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat(fd, &sbuf) < 0) {
|
||||
EPRINTLN("Could not fstat bootrom file \"%s\": %s",
|
||||
romfile, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
rom_size = sbuf.st_size;
|
||||
if (varfd < 0) {
|
||||
var_size = 0;
|
||||
} else {
|
||||
if (fstat(varfd, &sbuf) < 0) {
|
||||
fprintf(stderr, "Could not fstat bootrom variable file \"%s\": %s\n",
|
||||
varfile, strerror(errno));
|
||||
fprintf(stderr,
|
||||
"Could not fstat bootrom variable file \"%s\": %s\n",
|
||||
varfile, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
var_size = sbuf.st_size;
|
||||
}
|
||||
|
||||
@ -291,7 +306,10 @@ bootrom_loadrom(struct vmctx *ctx, const char *romfile)
|
||||
|
||||
rv = 0;
|
||||
done:
|
||||
if (varfd >= 0)
|
||||
close(varfd);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
free(romfile);
|
||||
return (rv);
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct vmctx;
|
||||
|
||||
void init_bootrom(struct vmctx *ctx);
|
||||
@ -45,6 +47,6 @@ enum {
|
||||
};
|
||||
int bootrom_alloc(struct vmctx *ctx, size_t len, int prot, int flags,
|
||||
char **region_out, uint64_t *gpa_out);
|
||||
int bootrom_loadrom(struct vmctx *ctx, const char *romfile);
|
||||
int bootrom_loadrom(struct vmctx *ctx, const nvlist_t *nvl);
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/vmm.h>
|
||||
#include <machine/vmm_snapshot.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -95,13 +96,24 @@ lpc_device_parse(const char *opts)
|
||||
{
|
||||
int unit, error;
|
||||
char *str, *cpy, *lpcdev, *node_name;
|
||||
const char *romfile, *varfile;
|
||||
|
||||
error = -1;
|
||||
str = cpy = strdup(opts);
|
||||
lpcdev = strsep(&str, ",");
|
||||
if (lpcdev != NULL) {
|
||||
if (strcasecmp(lpcdev, "bootrom") == 0) {
|
||||
set_config_value("lpc.bootrom", str);
|
||||
romfile = strsep(&str, ",");
|
||||
if (romfile == NULL) {
|
||||
errx(4, "invalid bootrom option \"%s\"", opts);
|
||||
}
|
||||
set_config_value("lpc.bootrom", romfile);
|
||||
|
||||
varfile = strsep(&str, ",");
|
||||
if (varfile != NULL) {
|
||||
set_config_value("lpc.bootvars", varfile);
|
||||
}
|
||||
|
||||
error = 0;
|
||||
goto done;
|
||||
}
|
||||
@ -204,13 +216,14 @@ lpc_init(struct vmctx *ctx)
|
||||
{
|
||||
struct lpc_uart_softc *sc;
|
||||
struct inout_port iop;
|
||||
const char *backend, *name, *romfile;
|
||||
const char *backend, *name;
|
||||
char *node_name;
|
||||
int unit, error;
|
||||
const nvlist_t *nvl;
|
||||
|
||||
romfile = get_config_value("lpc.bootrom");
|
||||
if (romfile != NULL) {
|
||||
error = bootrom_loadrom(ctx, romfile);
|
||||
nvl = find_config_node("lpc");
|
||||
if (nvl != NULL && nvlist_exists(nvl, "bootrom")) {
|
||||
error = bootrom_loadrom(ctx, nvl);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user