mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 05:52:36 +02:00
util/nvmutil: limit rw size on specific commands
i previously had this as a speed optimisation, but removed it because it wouldn't make any real speed difference, on most modern file systems / kernels. however, this also has the dual purpose of ensuring only what was verified gets written, on operations that only touch the NVM area, since this relies on checksum verification. therefore, i have re-added this feature, but under the new design of nvmutil. it is done policy-based, instead of having if/else for specific commands. Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
+49
-18
@@ -214,6 +214,7 @@ struct commands {
|
|||||||
uint8_t arg_part;
|
uint8_t arg_part;
|
||||||
uint8_t chksum_read;
|
uint8_t chksum_read;
|
||||||
uint8_t chksum_write;
|
uint8_t chksum_write;
|
||||||
|
size_t rw_size; /* within the 4KB GbE part */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -223,12 +224,14 @@ static const struct commands command[] = {
|
|||||||
{ CMD_DUMP, "dump", cmd_dump, ARGC_3,
|
{ CMD_DUMP, "dump", cmd_dump, ARGC_3,
|
||||||
NO_INVERT, SET_MOD_OFF,
|
NO_INVERT, SET_MOD_OFF,
|
||||||
ARG_NOPART,
|
ARG_NOPART,
|
||||||
SKIP_CHECKSUM_READ, SKIP_CHECKSUM_WRITE },
|
SKIP_CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
|
||||||
|
NVM_SIZE },
|
||||||
|
|
||||||
{ CMD_SETMAC, "setmac", cmd_setmac, ARGC_3,
|
{ CMD_SETMAC, "setmac", cmd_setmac, ARGC_3,
|
||||||
NO_INVERT, SET_MOD_OFF,
|
NO_INVERT, SET_MOD_OFF,
|
||||||
ARG_NOPART,
|
ARG_NOPART,
|
||||||
CHECKSUM_READ, CHECKSUM_WRITE },
|
CHECKSUM_READ, CHECKSUM_WRITE,
|
||||||
|
NVM_SIZE },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OPTIMISATION: Read inverted, so no copying is needed.
|
* OPTIMISATION: Read inverted, so no copying is needed.
|
||||||
@@ -236,7 +239,8 @@ static const struct commands command[] = {
|
|||||||
{ CMD_SWAP, "swap", NULL, ARGC_3,
|
{ CMD_SWAP, "swap", NULL, ARGC_3,
|
||||||
PART_INVERT, SET_MOD_BOTH,
|
PART_INVERT, SET_MOD_BOTH,
|
||||||
ARG_NOPART,
|
ARG_NOPART,
|
||||||
CHECKSUM_READ, SKIP_CHECKSUM_WRITE },
|
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
|
||||||
|
GBE_PART_SIZE },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OPTIMISATION: Read inverted, so no copying is needed.
|
* OPTIMISATION: Read inverted, so no copying is needed.
|
||||||
@@ -245,7 +249,8 @@ static const struct commands command[] = {
|
|||||||
{ CMD_COPY, "copy", NULL, ARGC_4,
|
{ CMD_COPY, "copy", NULL, ARGC_4,
|
||||||
PART_INVERT, SET_MOD_N,
|
PART_INVERT, SET_MOD_N,
|
||||||
ARG_PART,
|
ARG_PART,
|
||||||
CHECKSUM_READ, SKIP_CHECKSUM_WRITE },
|
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
|
||||||
|
GBE_PART_SIZE },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The non-target part will not be read.
|
* The non-target part will not be read.
|
||||||
@@ -253,7 +258,8 @@ static const struct commands command[] = {
|
|||||||
{ CMD_BRICK, "brick", cmd_brick, ARGC_4,
|
{ CMD_BRICK, "brick", cmd_brick, ARGC_4,
|
||||||
NO_INVERT, SET_MOD_OFF,
|
NO_INVERT, SET_MOD_OFF,
|
||||||
ARG_PART,
|
ARG_PART,
|
||||||
CHECKSUM_READ, SKIP_CHECKSUM_WRITE },
|
CHECKSUM_READ, SKIP_CHECKSUM_WRITE,
|
||||||
|
NVM_SIZE },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The non-target part will not be read.
|
* The non-target part will not be read.
|
||||||
@@ -261,7 +267,8 @@ static const struct commands command[] = {
|
|||||||
{ CMD_SETCHECKSUM, "setchecksum", cmd_setchecksum, ARGC_4,
|
{ CMD_SETCHECKSUM, "setchecksum", cmd_setchecksum, ARGC_4,
|
||||||
NO_INVERT, SET_MOD_OFF,
|
NO_INVERT, SET_MOD_OFF,
|
||||||
ARG_PART,
|
ARG_PART,
|
||||||
SKIP_CHECKSUM_READ, CHECKSUM_WRITE },
|
SKIP_CHECKSUM_READ, CHECKSUM_WRITE,
|
||||||
|
NVM_SIZE },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_CMD_LEN 50
|
#define MAX_CMD_LEN 50
|
||||||
@@ -364,6 +371,7 @@ static void
|
|||||||
sanitize_command_index(size_t c)
|
sanitize_command_index(size_t c)
|
||||||
{
|
{
|
||||||
uint8_t mod_type;
|
uint8_t mod_type;
|
||||||
|
size_t gbe_rw_size;
|
||||||
|
|
||||||
check_command_num(c);
|
check_command_num(c);
|
||||||
|
|
||||||
@@ -384,15 +392,14 @@ sanitize_command_index(size_t c)
|
|||||||
|
|
||||||
mod_type = command[c].set_modified;
|
mod_type = command[c].set_modified;
|
||||||
switch (mod_type) {
|
switch (mod_type) {
|
||||||
case SET_MOD_0:
|
case SET_MOD_0:
|
||||||
case SET_MOD_1:
|
case SET_MOD_1:
|
||||||
case SET_MOD_N:
|
case SET_MOD_N:
|
||||||
case SET_MOD_BOTH:
|
case SET_MOD_BOTH:
|
||||||
case SET_MOD_OFF:
|
case SET_MOD_OFF:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
err(EINVAL, "Unsupported set_mod type: %u",
|
err(EINVAL, "Unsupported set_mod type: %u", mod_type);
|
||||||
mod_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_bin(command[c].invert, "cmd.invert");
|
check_bin(command[c].invert, "cmd.invert");
|
||||||
@@ -405,6 +412,20 @@ sanitize_command_index(size_t c)
|
|||||||
CHECKSUM_READ, "CHECKSUM_READ");
|
CHECKSUM_READ, "CHECKSUM_READ");
|
||||||
check_enum_bin(SKIP_CHECKSUM_WRITE, "SKIP_CHECKSUM_WRITE",
|
check_enum_bin(SKIP_CHECKSUM_WRITE, "SKIP_CHECKSUM_WRITE",
|
||||||
CHECKSUM_WRITE, "CHECKSUM_WRITE");
|
CHECKSUM_WRITE, "CHECKSUM_WRITE");
|
||||||
|
|
||||||
|
gbe_rw_size = command[c].rw_size;
|
||||||
|
|
||||||
|
switch (gbe_rw_size) {
|
||||||
|
case GBE_PART_SIZE:
|
||||||
|
case NVM_SIZE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err(EINVAL, "Unsupported rw_size: %zu", gbe_rw_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gbe_rw_size > GBE_PART_SIZE)
|
||||||
|
err(EINVAL, "rw_size larger than GbE part: %zu",
|
||||||
|
gbe_rw_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -614,11 +635,16 @@ read_gbe_file(void)
|
|||||||
static void
|
static void
|
||||||
read_gbe_file_part(size_t p)
|
read_gbe_file_part(size_t p)
|
||||||
{
|
{
|
||||||
|
size_t gbe_rw_size = command[cmd_index].rw_size;
|
||||||
|
|
||||||
void *mem_offset =
|
void *mem_offset =
|
||||||
gbe_mem_offset(p ^ command[cmd_index].invert, "pread");
|
gbe_mem_offset(p ^ command[cmd_index].invert, "pread");
|
||||||
|
|
||||||
read_file_exact(gbe_fd, mem_offset,
|
read_file_exact(gbe_fd, mem_offset,
|
||||||
GBE_PART_SIZE, gbe_file_offset(p, "pread"), fname, "pread");
|
gbe_rw_size, gbe_file_offset(p, "pread"), fname, "pread");
|
||||||
|
|
||||||
|
printf("Read %zu bytes from part %zu: %s\n",
|
||||||
|
gbe_rw_size, p, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1038,16 +1064,21 @@ write_gbe_file_part(size_t p)
|
|||||||
{
|
{
|
||||||
int retry;
|
int retry;
|
||||||
ssize_t rval;
|
ssize_t rval;
|
||||||
|
size_t gbe_rw_size;
|
||||||
|
|
||||||
if (gbe_fd == -1)
|
if (gbe_fd == -1)
|
||||||
err(ECANCELED, "Trying to write bad gbe_fd: %s", fname);
|
err(ECANCELED, "Trying to write bad gbe_fd: %s", fname);
|
||||||
|
|
||||||
|
gbe_rw_size = command[cmd_index].rw_size;
|
||||||
|
|
||||||
for (retry = 0; retry < MAX_RETRY_RW; retry++) {
|
for (retry = 0; retry < MAX_RETRY_RW; retry++) {
|
||||||
rval = pwrite(gbe_fd, gbe_mem_offset(p, "pwrite"),
|
rval = pwrite(gbe_fd, gbe_mem_offset(p, "pwrite"),
|
||||||
GBE_PART_SIZE, gbe_file_offset(p, "pwrite"));
|
gbe_rw_size, gbe_file_offset(p, "pwrite"));
|
||||||
|
|
||||||
if (rval == GBE_PART_SIZE) {
|
if (rval == (ssize_t)gbe_rw_size) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
printf("Wrote %zu bytes to part %zu: %s\n",
|
||||||
|
gbe_rw_size, p, fname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user