Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
224 changes: 183 additions & 41 deletions handler.c

Large diffs are not rendered by default.

36 changes: 30 additions & 6 deletions handler_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,31 +49,56 @@ static struct {
static void
io_port_writel(uint64_t offset, uint64_t size, uint32_t val)
{
xen_pfn_t pfns[SHMEM_PAGES];
xen_pfn_t pfns[SHMEM_PAGES_V2_MAX];
void *shmem;
UINT32 version, nr_pages;
enum command_t command;
int i;
uint8_t *ptr;
EFI_STATUS status;

if (offset != 0 || size != sizeof(uint32_t)) {
DBG("Expected size 4, offset 0. Got %" PRIu64 ", %" PRIu64 ".\n", size, offset);
return;
}

for (i = 0; i < SHMEM_PAGES; i++)
for (i = 0; i < SHMEM_PAGES_V2_MAX; i++)
pfns[i] = val + i;
DBG("io_port write\n");

/* Only the first page is wanted for nr_pages detection */
shmem = xenforeignmemory_map(io_info.fmem,
io_info.domid,
PROT_READ | PROT_WRITE,
SHMEM_PAGES, pfns, NULL);
1, pfns, NULL);
if (!shmem) {
DBG("map foreign range failed (snoop): %d\n", errno);
return;
}

ptr = shmem;
/* nr_pages is the only thing we're interested in here */
status = snoop_command(&ptr, &version, &nr_pages, &command);

xenforeignmemory_unmap(io_info.fmem, shmem, 1);

if (status != EFI_SUCCESS) {
DBG("snoop_command refused version data\n");
return;
}

shmem = xenforeignmemory_map(io_info.fmem,
io_info.domid,
PROT_READ | PROT_WRITE,
nr_pages, pfns, NULL);
if (!shmem) {
DBG("map foreign range failed: %d\n", errno);
return;
}

dispatch_command(shmem);
dispatch_snooped_command(shmem, version, nr_pages, command);

xenforeignmemory_unmap(io_info.fmem, shmem, SHMEM_PAGES);
xenforeignmemory_unmap(io_info.fmem, shmem, nr_pages);

}

Expand All @@ -85,4 +110,3 @@ setup_handler_io_port(domid_t domid, xenforeignmemory_handle *fmem) {

return register_io_port_writel_handler(HANDLER_PORT_ADDRESS, io_port_writel);
}

47 changes: 41 additions & 6 deletions include/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,41 @@

#include "efi.h"

#define PAGE_SIZE 4096
#define SHMEM_PAGES_V1 16
/* Consumers shouldn't use this value, but should stick to SHMEM_PAGES_V2_MAX */
#define SHMEM_PAGES_V2_MIN 18
#define SHMEM_PAGES_V2_MAX 32

#define NAME_LIMIT 4096 /* Maximum length of name */
#define DATA_LIMIT 57344 /* Maximum length of a single variable */
#define TOTAL_LIMIT 131072 /* Maximum total storage */

/*
* Maximum length of a single variable. To ensure that there's sufficient room
* for variables in the communication buffer, SHMEM_PAGES must be high enough to
* cover the data limit + 1 page (4096 bytes) for the variable name + 1 page for
* protocol overhead.
*/
#define DATA_LIMIT(shmem_pages) (((shmem_pages) - 2) * PAGE_SIZE)

/* The following limits must respect the minimum prescribed by WHCP. */

#define DATA_LIMIT_V1 DATA_LIMIT(SHMEM_PAGES_V1)
/*
* For now, DATA_LIMIT_V2 and SHMEM_PAGES_V2_MIN are coupled: DATA_LIMIT_V2 is
* calculated from SHMEM_PAGES_V2_MIN, and one can't be increased without
* increasing the other.
*
* However, there's reserved headroom in SHMEM_PAGES_V2_MAX for later silently
* increasing DATA_LIMIT_V2; consumers should stick to SHMEM_PAGES_V2_MAX and
* not worry about this.
*/
#define DATA_LIMIT_V2 DATA_LIMIT(SHMEM_PAGES_V2_MIN)

/* For non-protocol uses */
#define DATA_LIMIT_MAX DATA_LIMIT_V2

/* Maximum total storage */
#define TOTAL_LIMIT 131072

/*
* A single variable takes up a minimum number of bytes.
Expand All @@ -46,10 +78,6 @@
#define VARIABLE_SIZE_OVERHEAD 128
#define MAX_VARIABLE_COUNT (TOTAL_LIMIT / VARIABLE_SIZE_OVERHEAD)

#define PAGE_SIZE 4096
#define SHMEM_PAGES 16
#define SHMEM_SIZE (SHMEM_PAGES * PAGE_SIZE)

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

enum command_t {
Expand All @@ -74,6 +102,13 @@ struct efi_variable {

extern struct efi_variable *var_list;

UINTN data_limit(UINT32 version);
EFI_STATUS snoop_command(uint8_t **comm_buf, UINT32 *out_version,
UINT32 *out_nr_pages, enum command_t *out_command);
void skip_command(uint8_t **comm_buf, UINT32 version, UINT32 nr_pages,
enum command_t command);
void dispatch_snooped_command(uint8_t *comm_buf, UINT32 version, UINT32 nr_pages,
enum command_t command);
void dispatch_command(uint8_t *comm_buf);
bool setup_crypto(void);
bool setup_variables(void);
Expand Down
Loading