When err() is called, it is intended that nvmutil will
always exit with non-zero status, but with errno as the
return value. Ensure that errno is *not* zero.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Make word() a macro, simplify err_if().
Could also make setWord() a macro if I forego certain
optimisations, but I'll leave it as-is.
Signed-off-by: Leah Rowe <leah@libreboot.org>
After /dev/urandom (for MAC address randomisation) and
the GbE file have been handled, unveil them. Unveil is
a system call provided by OpenBSD that, when called,
restricts access only to the files and/or directories
specified, each given specific permissions.
You can learn more about unveil here:
https://man.openbsd.org/unveil.2
An ifdef rule makes nvmutil only use unveil on OpenBSD,
because it's not available anywhere else. This is the same
as with the pledge() system call.
Where invalid arguments are given, and no action performed,
pledge promises are also reduced to just stdio, preventing
any writes to files, or reads from files.
Signed-off-by: Leah Rowe <leah@libreboot.org>
After reading a file, remove rpath.
When removing rpath, also remove wpath if flags
are not to O_RDONLY (read-only disk operation).
When wpath is permitted, and a file was successfully
written, remove wpath.
In order to permit /dev/urandom access in rhex(),
I call it as a void just before re-calling pledge.
The rhex() function has been written in such a way
that /dev/urandom only needs to be read *once*.
Signed-off-by: Leah Rowe <leah@libreboot.org>
I assumed wpath was all that's needed, but this simply
allows writes.
rpath must be specified alongside wpath, for reads.
Signed-off-by: Leah Rowe <leah@libreboot.org>
The utils that are pledged checked HAVE_PLEDGE which was
bogus. OpenBSD defines __OpenBSD__, which you can check
for in ifdef.
This change makes nvmutil and spkmodem-recv *actually*
use pledge, when the utils are compiled on OpenBSD.
Signed-off-by: Leah Rowe <leah@libreboot.org>
It will only be used on OpenBSD. Other operating
systems will behave in the same way.
Pledge is feature specific to OpenBSD that
restricts system operations, for security:
https://man.openbsd.org/pledge.2
Signed-off-by: Leah Rowe <leah@libreboot.org>
printf outputs to stdout, which is line buffered
by default.
Adding a -u option to disable buffering.
Exit when a non-support flag is given, but adhere
to current behaviour when no flag is given.
Signed-off-by: Leah Rowe <leah@libreboot.org>
They do not need to be initialised zero, because
global variables are always zero by default,
unless set differently by the programmer.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Imported from util/spkmodem_recv at coreboot
revision:
e70bc423f9a2e1d13827f2703efe1f9c72549f20
This is a client for spkmodem, to allow serial
console via PC speaker.
I've decided to import it in lbmk, because I
heavily modified it. The patches will be
applied next.
Signed-off-by: Leah Rowe <leah@libreboot.org>
the deleted patch (in this commit) was written to fix an
issue theoretically; it hasn't been fully tested, and some
people have reported strange issues since this patch was
merged - there is no proof that this patch causes them, but
removing this patch is the correct thing to do regardless
when nicholas added this, he removed the README because it's
going on libreboot.org instead. however, i merged a WIP version
of his page for now because i want to get the e6400 going in
libreboot sooner. so, temp-readding this README. will just
link to this on codeberg or something, from the lb docs
NOTE: I didn't write this README, hence author field set
in the commit. Nicholas wrote it, but I (Leah Rowe) am just
adding it. so, git author set to nicholas, not me
Adding it to lbmk for now as it is not yet in coreboot. If it is merged
into coreboot we can just reference the one there. The original README
will be incorporated into a new page on lbwww, so README.md just points
to a placeholder URL that should match the new page.
small nitpick, but i try to use openbsd style
since i like that style. upon further reading
of their style guidelines today, it was revealed
to me that for includes, they:
* sort sys/ includes alphabetically, at the top
* after sys/ includes, have an empty line
* includes for networking-related headers below that
* empty space below networking headers if there
* after that, have the rest of the includes, sorted
alphabetically
at least, that is my understanding. i have to admit,
it does look cleaner
not really that critical but why not do it?
don't download it. keep it in lbmk.
libreboot moved to codeberg for git hosting,
and i didn't want to keep lugging around an
extra git repo just for one tiny project.
word/setWord no longer mitigates endianness. instead,
all bytes are swapped after reading and before writing the
file, and only if the host is big endian
this improves performance on little endian hosts, which is
most machines, and the code is much simpler, so it's more
robust and less likely to break
mac address endianness made more clear in code, including
with a comment that explains it
(the nvm section contains little endian words, *except* the
mac address whose words are stored big endian)
reduce the number of calls to read() by using
bit shifts. when rnum is zero, read again. in
most cases, a nibble will not be zero, so this
will usually result in about 13-15 of of 16
nibbles being used. this is in comparison to
8 nibbles being used before, which means that
the number of calls to read() are roughly
halved. at the same time, the extra amount of
logic is minimal (and probably less) when
compiled, outside of calls to read(), because
shifting is better optimised (on 64-bit machines,
the uint64_t will be shifted with just a single
instruction, if the compiler is decent), whereas
the alternative would be to always precisely use
exactly 16 nibbles by counting up to 16, which
would involve the use of an and mask and still
need a shift, plus...
you get the point. this is probably the most
efficient code ever written, for generating
random numbers between the value of 0 and 15
the way nvmutil is designed, setWord() is only ever called
under non-error conditions. however, if one part is valid but
the other one isn't, and a command is run that touches both parts,
errno is non-zero write writeGbeFile is called
in situations where one part is valid, but the other isn't, AND the
writes to gbe (in memory) results in a non-change, writeGbeFile is
not called; in this situation, errno is not being reset, despite
non-error condition
this patch fixed the bug, resulting in zero status upon exit under
such conditions
the current code writes part 1 first, and part 0 next,
on the disk, due to the way the swap works.
with this change, swap still swaps the two parts of the file,
on disk, but writes the new file sequentially.
this change might speed up i/o on the file system, on HDDs.
on SSDs, this change likely makes no difference at all.
On many Lenovo GbE regions (in factory firmware), part 0 is
invalid but part 1 is valid.
This change means part 1 is checked first. If part 1 is valid,
part 0 won't be checked at all (due to how most C compilers
optimise).
Most people are just going to extract the factory GbE file,
modify it and re-insert it into the ROM image, so this causes
a nice speedup.
don't constantly open/close the file: /dev/urandom
only read 12 bytes at a time
because of this change, the readFromFile() function now only
handles gbe files
don't do xor swap. we know gbe2 is always 4KB higher than
gbe in memory, so we can just set gbe2 to the value of gbe,
and OR the size in bytes of 4KB into gbe2
this is only a marginal speed boost, negligible even, but it's
done for the lulz
similar to the last change by concept. we now write
individual 4KB blocks per part 0 and 1, at the end
of nvmutil, based on pointer values gbe and gbe2
instead of running memcpy, simply overwrite the pointer
this results in less I/O, thus more speed
instead of XOR-swapping every byte, have pointers to the
two parts and *XOR swap the pointers*. at the end of the
program execution, when writing, pwrite the two parts into
the same file
*This condition will probably never be met, but it is theoretically
possible that the code could still fail at this point. Catch all errors,
and exit, ruthlessly.
The code was only checking whether all of the bytes were read,
but there are other errors that can be caught via errno.
Enforce strict errno handling, when generating random
numbers for command `setmac`.
previously, it was always initialised, but now it's only
initialised if '?' is used on a mac address character in
command `setmac`
this is done by simply moving mac address character
randomisation to a separate function
If one of the checksums was valid, but the other was not,
errno would be set to E_CANCELED, but then the buffer would
be modified anyway; this is acceptable behaviour, and errno
would later be reset writing the GBE file, which is done
only on the condition that the buffer was modified, but
it's also a good idea to reset it here just in case.
This is not a bugfix, and no behavioural changes will be
observed by the user, but this may *prevent* a bug in the
future, so let's pre-fix that bug now.
in any C program, main() should not contain detailed logic.
ideally, the main() function should only be a skeleton, showing
the overall logic flow of the program. split writing gbe files
into a separate function, to satisfy this criteria.