after setting the checksum too
this is functionally no different, but setting it
at the start didn't sit right with me.
it's more logically correct to set it at the end,
in case any error did not result in an exit.
Signed-off-by: Leah Rowe <leah@libreboot.org>
We're checking if errno is ENOTDIR, not setting it;
the previous code would always return true, and then
set errno 0, which in the context of this code was
actually OK, so this patch makes no functional difference
in practise.
However, I'm a stickler for technical correctness. I caught
this when trying to compile with clang, because clang is
quite pedantic about checking for exactly this type of bug.
Signed-off-by: Leah Rowe <leah@libreboot.org>
previously, if the user ran:
./nvm GBE [MAC address]
it would error, treating the MAC as a command
now if only 3 arguments are provided, and the
3rd argument ins't a valid command, it's treated
as a MAC address and validated accordingly.
this should make nvmutil easier to use, because
I imagine a lot of users forget to use setmac
there's no reason we should be so pedantic. we
should allow it to be used flexibly like this
Signed-off-by: Leah Rowe <leah@libreboot.org>
On the 16KB and 128KB files, we still only need to
operate on 4KB at the start of each block, where the
block size is larger than 4KB.
The reason we deal with the entire 4KB block is because
the nvm words (in the 128 byte section) can define an
extended nvm area anywhere after 128 bytes, within the
128 byte block.
We could systematically read where that is being handled,
and handle it; we could then allocate less memory, and
read/write fewer bytes, but many block devices like SSDs
and flash drives have at least a 4KB erase block anyway,
so it's kinda pointless. saving memory would be nice, but
I don't really want to bloat the code.
This is a nice easy optimisation, to avoid wasting an
additional 8KB of memory when handling 16KB files, and
additional 120KB if handling 128KB files, since nf is
what determines how much memory will be allocated.
the alternative would be to use an mmap, and then we
could reasonably handle the idea above for only writing,
surgically, what we need: nvm words and extended nvm
words.
Signed-off-by: Leah Rowe <leah@libreboot.org>
./nvm gbe.bin
with this patch, the above example does the same as:
./nvm gbe.bin setmac
now you can simply specify the gbe file, and it will
randomise the mac address within it, and update the
nvm checksum word.
Signed-off-by: Leah Rowe <leah@libreboot.org>
this way, we still get an error exit for example
when trying to invalidate an already invalid
checksum; this error exit was disabled by the
last revisions.
Signed-off-by: Leah Rowe <leah@libreboot.org>
This is for user friendliness. Otherwise, many users
might try to dump afterward if they specified a random
MAC address.
This saves the user from having to re-run with the dump
command, thus saving time for the user.
Signed-off-by: Leah Rowe <leah@libreboot.org>
instead of setting errno in the for loop, set a variable
declaring that the mac was updated, and reset errno based
on that.
Signed-off-by: Leah Rowe <leah@libreboot.org>
if checksum verification passed, then we should reset
in case we're operating on a given part and the last
one checked was bad.
a catch-all reset is already performed in writeGbe,
but it's good to do it here too.
in practise, if the 2nd part (part 1) is what failed,
errno still wouldn't be reset.
Signed-off-by: Leah Rowe <leah@libreboot.org>
it will probably never happen, and this is technically
not an error condition of pread/pwrite, but we need it
to read and write that exact number of bytes, as per nf
Signed-off-by: Leah Rowe <leah@libreboot.org>
it wouldn't occur, on the current logic, but i wasn't
comfortable having the starting point (on little endian)
being higher than the checked endpoint, in case of
possible integer overflow as a result of future
modifications.
this is therefore a pre-emptive bug fix, because it doesn't
yet fix a bug, but it prevents a bug from being introduced.
Signed-off-by: Leah Rowe <leah@libreboot.org>
The 128-byte nvm area is all that we need to handle,
since that is the only thing we actually work on in
nvmutil, based on checksum verification; the latter
implies that bytes must be in the correct order.
The swap() function previously worked on the entire
block, e.g. 4KB on 8KB files, 8KB on 16KB files and
64KB on 128KB files, and it did this twice, so it would
have operated on anywhere between 8KB to 128KB of data.
It now only operates on 256 bytes at a maximum, or 128
bytes if only handling one block. This is a significant
performance optimisation, on big endian host CPUs.
Signed-off-by: Leah Rowe <leah@libreboot.org>
previous audits sizecoded nvmutil.c, reducing the sloccount,
but this resulted in unreadable code.
move the swap logic (swap parts) back to its own function,
for clarity.
Signed-off-by: Leah Rowe <leah@libreboot.org>
also cmd_brick
where the checksum is being corrected or bricked, we
only need to handle the 128-byte nvm area on one of
the parts
similarly, we only need to allocate half the gbe file
size when doing a copy command.
256 bytes still allocated for setmac (see previous
commit), because we verify both checksums and set both
parts if possible.
with this, nvmutil is now much more memory-efficient.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Allocate memory based on nf instead of partsize.
nf is the number of bytes actually read from each
part of the file.
Now if the user is running setmac for example,
256 bytes of memory will be allocated regardless
of gbe file size, whereas it would have previously
allocated 8KB, 16KB or 128KB depending on the file.
Signed-off-by: Leah Rowe <leah@libreboot.org>
We were allocating 128KB even if we only needed 8KB, for
example. It's not a lot of memory, but the principle of
the matter is that we must respect the user by not wasting
their memory.
The design of nvmutil is that it will never overflow, because
operations are mapped in memory to the exact size of the gbe
file, which can be 8KB, 16KB or 128KB, and this is enforced.
Signed-off-by: Leah Rowe <leah@libreboot.org>
The buf variable is only used once, and only so
that we can get a pointer. We can point to buf16
instead, for the same result.
The gbe pointer (size_t) is later converter to
a char * when writing back to the file.
Signed-off-by: Leah Rowe <leah@libreboot.org>
For example, if the brick command is used without specifying
a part number. Instead of saying "Invalid argument", show a
much more useful error message to help the user adapt.
Signed-off-by: Leah Rowe <leah@libreboot.org>
call pledge *much* earlier, and and lock everything down
much sooner. the point of pledge/unveil is precisely that
your program must operate under the most restrictive set
of conditions possible, and still function.
Signed-off-by: Leah Rowe <leah@libreboot.org>
tell the user exactly what they got wrong, instead
of simply printing "bad mac address", which is not
very helpful to the user
Signed-off-by: Leah Rowe <leah@libreboot.org>
See:
https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/client/platforms/alder-lake-mobile-p/intel-600-series-chipset-family-on-package-platform-controller-hub-pch-datash/spi0-for-flash/
The rules described there are universal, and replicated elsewhere
for many other platforms. The rules are simply:
* Flash descriptor is one block size, e.g. 4KB
* GbE is two block sizes, so if IfD is 4KB, GbE is 8KB
Intel defines 16KB and 128KB GbE files in specs, pertaining to
8KB and 64KB block sizes respectively.
The minimum size is 4KB blocksize, for 8KB GbE files which
we already supported. On larger block sizes, the same 4KB
parts are observed: a single 4KB IfD area at the start of
the block, and:
4KB GbE part at the start of the GbE region, and:
4KB GbE part at the start of GbE region plus block size
The empty space inbetween is padding, and we ignore it,
except when running swap/copy commands.
The nvmutil code has been modified, to create a 128KB buffer in
memory instead of 8KB, for loading GbE files.
Partsize is set to GbE file size divided by 2, and only the
area of memory we need to use is mapped; for example, if
we're loading a 8KB GbE file into memory, we only touch
the first 8KB part of the buffer, or first 16KB for 128KB
files.
In practise, we almost never see GbE files with sizes higher
than 8KB, but *we have seen it*, *AND NOW IT'S SUPPORTED!"
Signed-off-by: Leah Rowe <leah@libreboot.org>
We were checking directories *after* calling unveil, which
means that the sandboxing was incomplete; we only want files
to be accessed, not directories.
Signed-off-by: Leah Rowe <leah@libreboot.org>
A lot of size-coding was performed in prior audits, to
make the sloccount lower on nvmutil, but this resulted in
code that wasn't very human readable.
I've reversed some of it and added comments, for clarity.
Signed-off-by: Leah Rowe <leah@libreboot.org>
the user might have boot their kernel inside luks
inside lvm for some dumb reason
it's theoretically possible that the user would be
so silly indeed
Signed-off-by: Leah Rowe <leah@libreboot.org>
We were scanning a hardcoded set up LVM volumes, so in practise,
LVM boot didn't really work. We did this because scanning for
asterisk is slow on some machines. However, since LVM is the last
one, and since most users don't boot directly from LVM, it wasn't
that much of an issue in practise.
Signed-off-by: Leah Rowe <leah@libreboot.org>