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:
Corvin Köhne 2022-03-02 22:45:20 -09:00 committed by Robert Wing
parent f266082f11
commit 87f6367f10
4 changed files with 62 additions and 24 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}