util/nvmutil: unified I/O: stdout, urandom and gbe

everything is a file

Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
Leah Rowe
2026-03-10 04:02:28 +00:00
parent 6402a0fbe9
commit 80f3aac62d
+52 -63
View File
@@ -109,8 +109,6 @@ static void set_mac_nib(size_t mac_str_pos,
size_t mac_byte_pos, size_t mac_nib_pos); size_t mac_byte_pos, size_t mac_nib_pos);
static uint16_t hextonum(char ch_s); static uint16_t hextonum(char ch_s);
static uint16_t rhex(void); static uint16_t rhex(void);
static void read_file_exact(int fd, uint8_t *mem, size_t len,
off_t off, uint8_t plesen, const char *path);
static void write_mac_part(size_t partnum); static void write_mac_part(size_t partnum);
static void cmd_helper_dump(void); static void cmd_helper_dump(void);
static void print_mac_from_nvm(size_t partnum); static void print_mac_from_nvm(size_t partnum);
@@ -127,6 +125,8 @@ static void set_part_modified(size_t p);
static void check_nvm_bound(size_t pos16, size_t part); static void check_nvm_bound(size_t pos16, size_t part);
static void check_bin(size_t a, const char *a_name); static void check_bin(size_t a, const char *a_name);
static void write_gbe_file_part(size_t part); static void write_gbe_file_part(size_t part);
static void rw_file_exact(int fd, uint8_t *mem, size_t len,
off_t off, int rw_type, const char *path, const char *rw_type_str);
static off_t gbe_file_offset(size_t part, const char *f_op); static off_t gbe_file_offset(size_t part, const char *f_op);
static uint8_t *gbe_mem_offset(size_t part, const char *f_op); static uint8_t *gbe_mem_offset(size_t part, const char *f_op);
static off_t gbe_x_offset(size_t part, const char *f_op, static off_t gbe_x_offset(size_t part, const char *f_op,
@@ -224,6 +224,13 @@ static const char *argv0;
#define ARGC_3 3 #define ARGC_3 3
#define ARGC_4 4 #define ARGC_4 4
enum {
LESEN,
PLESEN,
SCHREIB,
PSCHREIB
};
/* /*
* Used as indices for command[] * Used as indices for command[]
* MUST be in the same order as entries in command[] * MUST be in the same order as entries in command[]
@@ -512,6 +519,9 @@ sanitize_command_index(size_t c)
if (command[c].flags != O_RDONLY && if (command[c].flags != O_RDONLY &&
command[c].flags != O_RDWR) command[c].flags != O_RDWR)
err(EINVAL, "invalid cmd.flags setting"); err(EINVAL, "invalid cmd.flags setting");
if (!((PLESEN > LESEN) && (SCHREIB > PLESEN) && (PSCHREIB > SCHREIB)))
err(EINVAL, "some rw type integers are the same");
} }
static void static void
@@ -698,9 +708,9 @@ read_gbe_file_part(size_t p)
uint8_t *mem_offset = uint8_t *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, rw_file_exact(gbe_fd, mem_offset,
gbe_rw_size, gbe_file_offset(p, "pread"), gbe_rw_size, gbe_file_offset(p, "pread"),
1, fname); PLESEN, fname, "pread");
} }
static void static void
@@ -938,42 +948,13 @@ rhex(void)
#ifdef NVMUTIL_ARC4RANDOM_BUF #ifdef NVMUTIL_ARC4RANDOM_BUF
arc4random_buf(rnum, n); arc4random_buf(rnum, n);
#else #else
read_file_exact(urandom_fd, rnum, n, 0, 0, rname); rw_file_exact(urandom_fd, rnum, n, 0, LESEN, rname, "read");
#endif #endif
} }
return (uint16_t)(rnum[--n] & 0xf); return (uint16_t)(rnum[--n] & 0xf);
} }
static void
read_file_exact(int fd, uint8_t *mem,
size_t len, off_t off, uint8_t plesen, const char *path)
{
ssize_t rval = -1;
ssize_t rc = 0;
if (fd == -1)
err(ECANCELED, "Trying to open bad fd: %s", path);
for (rc = 0; rc != (ssize_t)len; rc += rval) {
if (plesen)
rval = pread(fd, mem + rc, len - rc, off + rc);
else
rval = read(fd, mem + rc, len - rc);
if (rval > -1) {
if (!rval) /* prevent infinite loop */
err(EIO, "%s: read of 0 bytes", path);
continue;
}
if (errno != EINTR || rval < -1)
err(EIO, "%s", path);
errno = 0;
}
}
static void static void
write_mac_part(size_t partnum) write_mac_part(size_t partnum)
{ {
@@ -1075,12 +1056,8 @@ cmd_helper_cat(void)
static void static void
gbe_cat_buf(uint8_t *b) gbe_cat_buf(uint8_t *b)
{ {
size_t wc; rw_file_exact(STDOUT_FILENO, b, GBE_PART_SIZE, 0,
ssize_t w = 0; SCHREIB, "stdout", "write");
for (wc = 0; wc < GBE_PART_SIZE; wc += w)
if ((w = write(STDOUT_FILENO, b + wc, GBE_PART_SIZE - wc)) < 1)
err(EIO, "%s: stdout", fname);
} }
static void static void
@@ -1222,37 +1199,49 @@ check_bin(size_t a, const char *a_name)
static void static void
write_gbe_file_part(size_t p) write_gbe_file_part(size_t p)
{ {
int retry; size_t gbe_rw_size = command[cmd_index].rw_size;
ssize_t rval; uint8_t *mem_offset = gbe_mem_offset(p, "pwrite");
size_t gbe_rw_size;
if (gbe_fd == -1) rw_file_exact(gbe_fd, mem_offset,
err(ECANCELED, "%s: Trying to write bad gbe_fd", fname); gbe_rw_size, gbe_file_offset(p, "pwrite"),
PSCHREIB, fname, "pwrite");
}
gbe_rw_size = command[cmd_index].rw_size; static void
rw_file_exact(int fd, uint8_t *mem, size_t len,
off_t off, int rw_type, const char *path,
const char *rw_type_str)
{
ssize_t rval = -1;
ssize_t rc = 0;
for (retry = 0; retry < MAX_RETRY_RW; retry++) { if (fd < 0)
rval = pwrite(gbe_fd, gbe_mem_offset(p, "pwrite"), err(EIO, "%s: %s: Bad fd %d", path, rw_type_str, fd);
gbe_rw_size, gbe_file_offset(p, "pwrite")); if (!len)
err(EIO, "%s: %s: Zero length", path, rw_type_str);
if (rval == (ssize_t)gbe_rw_size) { for (rc = 0; rc != (ssize_t)len; rc += rval) {
errno = 0; if (rw_type == PSCHREIB)
printf("%s: Wrote %zu bytes to part %zu\n", rval = pwrite(fd, mem + rc, len - rc, off + rc);
fname, gbe_rw_size, p); else if (rw_type == SCHREIB)
return; rval = write(fd, mem + rc, len - rc);
else if (rw_type == PLESEN)
rval = pread(fd, mem + rc, len - rc, off + rc);
else if (rw_type == LESEN)
rval = read(fd, mem + rc, len - rc);
if (rval > -1) {
if (!rval) /* prevent infinite loop */
err(EIO, "%s: %s: 0-byte return",
path, rw_type_str);
continue;
} }
if (rval != -1) if (errno != EINTR || rval < -1)
err(ECANCELED, err(EIO, "%s: %s", path, rw_type_str);
"%s: Short pwrite of %zd bytes",
fname, rval);
if (errno != EINTR) errno = 0;
err(ECANCELED,
"%s: pwrite failed on p%zu", fname, p);
} }
err(EINTR, "%s: pwrite: max retries exceeded on p%zu", fname, p);
} }
/* /*