assimilate nvmutil documentation
parent
3ffcc8f093
commit
7034a9b745
|
@ -97,3 +97,29 @@ On GM45 laptops with ICH9M southbridge and Intel PHY module, the MAC address
|
|||
is hardcoded in boot flash, which means it can be changed if you re-flash.
|
||||
|
||||
See [ich9utils documentation](../install/ich9utils.md)
|
||||
|
||||
If *all* you want to do is change the MAC address, you might try `nvmutil`
|
||||
instead. See notes below:
|
||||
|
||||
Changing the MAC address on ivybridge/sandybridge/haswell (e.g. X230/T440p)
|
||||
=========================================================
|
||||
|
||||
See [nvmutil documentation](../install/nvmutil.md)
|
||||
|
||||
This tool was originally written for changing the MAC address on Intel
|
||||
Sandybridge, Ivybridge and Haswell platforms, but it can be used on any
|
||||
platform with a valid GbE region in flash, where an Intel Flash Descriptor
|
||||
is used; this includes older GM45+ICH9M machines supported by Libreboot.
|
||||
|
||||
The `ich9utils` program is more useful in an lbmk context, because it
|
||||
generates an entire Intel Flash Descriptor and GbE region from scratch;
|
||||
coreboot has a similar method in its build system, using its own utility
|
||||
called bincfg, but this tool is unused in lbmk.
|
||||
|
||||
No tool like ich9utils exists for these boards yet, but lbmk includes the IFD
|
||||
and GbE files in-tree (Intel ME is handled by extracting from Lenovo updates,
|
||||
which the build system automatically fetches from the internet).
|
||||
|
||||
You can use `nvmutil` to change the existing MAC address in a GbE region. This
|
||||
sets the "hardcoded" MAC address, typically a globally assigned one set by
|
||||
the vendor.
|
||||
|
|
|
@ -3,6 +3,9 @@ title: ich9utils
|
|||
x-toc-enable: true
|
||||
...
|
||||
|
||||
If all you want to do is change the MAC address, you might use `nvmutil`
|
||||
instead. See: [nvmutil documentation](../install/nvmutil.md).
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
|
|
|
@ -123,6 +123,12 @@ Which systems are supported?
|
|||
|
||||
[Refer to the hardware compatibility page](../hardware/)
|
||||
|
||||
MAC address on Sandybridge/Ivybridge/Haswell (e.g. X230, X220, T440p)
|
||||
=====================================================================
|
||||
|
||||
You can change the MAC address in flash, on these machines. See:
|
||||
[nvmutil documentation](nvmutil.md)
|
||||
|
||||
MAC address on GM45+ICH9M hardware (ThinkPad X200/R400/T400/T500/W500)
|
||||
======================================================================
|
||||
|
||||
|
@ -130,7 +136,8 @@ The MAC address is stored in a region of the boot flashed called *GbE NVM*
|
|||
which is short for *gigabit ethernet non-volatile memory*. Refer to the
|
||||
following article:
|
||||
|
||||
[ich9utils documentation](ich9utils.md)
|
||||
[ich9utils documentation](ich9utils.md) (you can also use nvmutil, see link
|
||||
above)
|
||||
|
||||
libreboot puts a default MAC address in the available ROM images, but this is
|
||||
a generic MAC address and it's identical on every ROM image. Technically, you
|
||||
|
|
|
@ -71,6 +71,9 @@ For example:
|
|||
|
||||
./blobutil inject -r x230_libreboot.rom -b x230_12mb -m 00:f6:f0:40:71:fd
|
||||
|
||||
NOTE: this makes use of `nvmutil`, which you can read more about in
|
||||
the [nvmutil documentation](nvmutil.md).
|
||||
|
||||
Splitting The Rom
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -0,0 +1,555 @@
|
|||
---
|
||||
title: nvmutil: MAC address changer and/or randomiser for IFD/GbE
|
||||
x-toc-enable: true
|
||||
...
|
||||
|
||||
With this software, you can change the MAC address inside GbE regions
|
||||
on any system that uses an Intel Flash Descriptor.
|
||||
|
||||
This is the reference documentation for `nvmutil`, but an automated script
|
||||
using nvmutil is available for ivy/sandybridge and haswell hardware, when
|
||||
inserting blobs, which you can use to change the MAC address. See:
|
||||
|
||||
[docs/install/ivy_has_common.md](ivy_has_common.md)
|
||||
|
||||
You can use the documentation below, if you wish to use `nvmutil` manually.
|
||||
Continue reading...
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This is the manual for `nvmutil`, included in the Libreboot,
|
||||
build system (lbmk) under `util/nvmutil/`. This program lets you modify
|
||||
the MAC address, correct/verify/invalidate checksums,
|
||||
swap/copy and dump regions on Intel PHY NVM images,
|
||||
which are small binary configuration files that go
|
||||
in flash, for Gigabit (ethernet) Intel NICs.
|
||||
|
||||
This software is largely targeted at coreboot users,
|
||||
but it can be used on most modern Intel systems, or
|
||||
most systems from about 2008/2009 onwards.
|
||||
|
||||
NOTE: Libreboot X200/X200T/X200S/T400/T400S/T500/W500/R400
|
||||
users should know that this software does *not*
|
||||
replace `ich9gen`, because that program generates entire
|
||||
ICH9M IFD+GbE regions, in addition to letting you set the
|
||||
MAC address. *This* program, `nvmutil`, can *also* set
|
||||
the MAC address on those machines, but it operates on a
|
||||
single GbE dump that is already created.
|
||||
|
||||
This program is operated on dumps of the GbE NVM image,
|
||||
which normally goes in the boot flash (alongside BIOS/UEFI
|
||||
or coreboot, IFD and other regions in the flash). The first
|
||||
half of this README is dedicated to precisely this, telling
|
||||
you how to dump or otherwise acquire that file; the second
|
||||
half of this README then tells you how to operate on it,
|
||||
using `nvmutil`.
|
||||
|
||||
How to download newer versions
|
||||
==============================
|
||||
|
||||
Simply pull down the latest changes in `lbmk.git`. The `nvmutil`
|
||||
software is now part of lbmk, since 17 November 2022.
|
||||
|
||||
More info about git:
|
||||
|
||||
* <https://git-scm.com/>
|
||||
|
||||
Context
|
||||
=======
|
||||
|
||||
On many Intel systems with an IFD (Intel Flash Descriptor), the
|
||||
Intel PHY (Gigabit Ethernet) stores its configuration, binary
|
||||
encoded, into a special region of the main boot flash, alongside
|
||||
other flash regions such as: IFD, ME, BIOS.
|
||||
|
||||
This includes many configurations, such as your MAC address.
|
||||
The purpose of nvmutil project, is precisely to allow you to change your
|
||||
MAC address. Many other useful features are also provided.
|
||||
|
||||
Intel defines this as the *Gigabit Ethernet Non-Volative Memory* or
|
||||
just *NVM* for short. It is a 128-byte section, consisting of 64
|
||||
words that are 2 bytes, stored in little-endian byte order.
|
||||
|
||||
Newer Intel PHYs define an *extended* area, which starts
|
||||
immediately after the main one, but the `nvmutil` program
|
||||
does not modify or manipulate these in any way.
|
||||
|
||||
The final word in the NVM section is the *checksum*; all words
|
||||
must add up, truncated, to the value `0xBABA`. The hardware
|
||||
itself does not calculate or validate this, and will in
|
||||
fact work nicely, but software such as Linux will check
|
||||
that this is correct. If the checksum is invalid, your
|
||||
kernel will refuse to make use of the NIC.
|
||||
|
||||
This NVM section is the first 128 bytes of a 4KB region in flash.
|
||||
This 4KB region is then repeated, to make an 8KB region in
|
||||
flash, known as the *GbE region*. In `nvmutil`, the first part
|
||||
is referred to as *part 0* and the second part as *part 1*.
|
||||
|
||||
Known compatible PHYs
|
||||
---------------------
|
||||
|
||||
TODO: write a full list her ofe what actual PHYs are known to work.
|
||||
|
||||
It's probably all of them, but some newer ones might have
|
||||
changed the standard by which they are configured. This
|
||||
program actively avoids working on files that have
|
||||
invalid checksums, on most commands, precisely so that
|
||||
the user does not inadvertently use it on incompatible
|
||||
files; it is assumed that intel would later change the
|
||||
file size and/or checksum value and/or checksum location.
|
||||
|
||||
How to obtain the GbE file
|
||||
==========================
|
||||
|
||||
The chip containing your BIOS/UEFI firmware (or coreboot) has
|
||||
it, if you have an Intel PHY for gigabit ethernet.
|
||||
|
||||
The sections below will teach you how to obtain the GbE file,
|
||||
containing your NIC's configuration. This is the part that
|
||||
many people will struggle with, so we will dedicated an
|
||||
entire next section to it:
|
||||
|
||||
Use flashrom
|
||||
------------
|
||||
|
||||
If you wish to operate on the GbE section that's already
|
||||
flashed, you should *dump* the current full ROM image.
|
||||
If you already have a ROM image, you do not need to dump
|
||||
it, so you can skip this section.
|
||||
|
||||
Download flashrom here:
|
||||
|
||||
* <https://flashrom.org/>
|
||||
|
||||
Using recent flashrom versions, you can extract this region. If
|
||||
your regions are unlocked, you can run flashrom on the target
|
||||
system, like so:
|
||||
|
||||
flashrom -p internal -r rom.bin
|
||||
|
||||
If your system has two flash chips, the GbE region is usually
|
||||
stored on SPI1 (not SPI2). Otherwise, it may be that you have
|
||||
a single-flash setup. In that case, it's recommended to dump
|
||||
both chips, as `spi1.rom` and `spi2.rom`; you can then cat
|
||||
them together:
|
||||
|
||||
cat spi1.rom spi2.rom > rom.bin
|
||||
|
||||
If your GbE region is locked (per IFD settings), you can dump
|
||||
and flash it using external flashing equipment. The Libreboot
|
||||
project has a handy guide for this; it can be used for reading
|
||||
from and writing to the chip. See:
|
||||
|
||||
* <https://libreboot.org/docs/install/spi.html>
|
||||
|
||||
If you're using an external programmer, the `-p internal`
|
||||
option should be changed accordingly. Read flashrom
|
||||
documentation, and make sure you have everything
|
||||
properly configured.
|
||||
|
||||
Use ifdtool
|
||||
-----------
|
||||
|
||||
NOTE: This has only been tested on systems that use IFDv1
|
||||
(Intel Flash Descriptor, version 1). This distinction, between
|
||||
v1 and v2, is made in the `ifdtool` source code, which you
|
||||
should read if you're interested. Intel`s v2 specification
|
||||
has more regions in it, whereas v1 systems usually
|
||||
defined: IFD, GbE, PD, ME and BIOS regions.
|
||||
|
||||
The `ifdtool` program is a powerful tool, allowing you to
|
||||
manipulate Intel Flash Descriptors. It's part of coreboot,
|
||||
available in the `coreboot.git` repository
|
||||
under `util/ifdtool/`. Just go in there and build it
|
||||
with `make`, to get an ifdtool binary.
|
||||
|
||||
To make internal flashing possible later on, you might do:
|
||||
|
||||
ifdtool --unlock rom.bin
|
||||
|
||||
Running this command will create a modified image,
|
||||
named `rom.bin.new`. This file will have all regions set
|
||||
to read-write, per configuration in the Intel Flash Descriptor.
|
||||
|
||||
In addition to unlocked regions, you may wish to *neuter* the
|
||||
Intel Management Engine, removing all the nasty spying features
|
||||
from it, using `me_cleaner`. See:
|
||||
|
||||
* <https://github.com/corna/me_cleaner>
|
||||
* Also available in `coreboot.git`, undir `util/`
|
||||
|
||||
The `me_cleaner` program is outside the scope of this
|
||||
article, so you should read their documentation.
|
||||
|
||||
Now run this:
|
||||
|
||||
ifdtool -x rom.bin
|
||||
|
||||
Several files will be created, and the one you need to
|
||||
operate on is named `flashregion_3_gbe.bin` so please
|
||||
ensure that you have this file.
|
||||
|
||||
Read the notes below about how to use the `nvmutil` program,
|
||||
operating on this file. When you're done, you can insert the
|
||||
modified GbE file back into your ROM image, like so:
|
||||
|
||||
ifdtool -i gbe:flashregion_3_gbe.bin rom.bin
|
||||
|
||||
This will create the file `rom.bin.new`, which contains
|
||||
your modified GbE section with the NVM images inside; this
|
||||
includes your MAC address.
|
||||
|
||||
Refer to flashrom documentation. You may flash the new ROM
|
||||
like so, if running on the same system and the regions are
|
||||
read-write:
|
||||
|
||||
flashrom -p internal -w rom.bin.new
|
||||
|
||||
Newer versions of flashrom support flashing just the specified
|
||||
region, like so:
|
||||
|
||||
flashrom -p internal --ifd -i gbe -w rom.bin.new
|
||||
|
||||
If you're running flashrom from host CPU on the target
|
||||
system, and it's dual flash, you can just flash the
|
||||
concatenated image, which you created earlier by running
|
||||
the `cat` program; dual-IC flash configurations appear to
|
||||
your operating system as one large flash area, as though
|
||||
it were a single chip.
|
||||
|
||||
If you're using an external programmer, you should change
|
||||
the `-p internal` parameter to something else. In this
|
||||
situation, you should re-split the file accordingly, if
|
||||
you have a dual-IC flash set, like so:
|
||||
|
||||
dd if=rom.bin.new of=spi2.rom bs=1M skip=8
|
||||
dd if=rom.bin.new of=spi1.rom bs=1M count=8
|
||||
|
||||
These files would then be flashed externally, separately,
|
||||
using an external programmer.
|
||||
|
||||
The *above* example (using `dd`) is for setups with 12MB
|
||||
flash, where you have 8MB as SPI1 and 4MB as SPI2. SPI1
|
||||
would contain the IFD, and SPI2 is the upper flash area
|
||||
containing your bootblock; GbE is probably located in
|
||||
SPI1. You should adjust the above parameters, according
|
||||
to your configuration.
|
||||
|
||||
How to compile source code
|
||||
==========================
|
||||
|
||||
The nvmutil programs will work just fine, on any BSD operating
|
||||
system, or unix-like system such as GNU+Linux, Chimera Linux or
|
||||
Alpine Linux. You must be sure to have toolchains installed, for
|
||||
building; a normal libc, C compiler and linker should be enough.
|
||||
GCC and LLVM have all these things included, so use whichever one
|
||||
you want.
|
||||
|
||||
As of nvmutil 20220808, OpenBSD `pledge(2)` is used in the code.
|
||||
This is done with an `ifdef` rule, so that the code still compiles
|
||||
on other systems. When the `dump` command is specified, pledge
|
||||
will use these promises: `stdio rpath`. When any other command
|
||||
is used, these pledge promises will be used: `stdio wpath`.
|
||||
|
||||
The `nvmutil` software has been build-tested on `Clang`, `GCC`
|
||||
and `tcc`. Only standard library functions (plus `err.h`) are
|
||||
used, so you don't need any extra libraries.
|
||||
|
||||
How to compile it
|
||||
-----------------
|
||||
|
||||
First, ensure that the current working directory is your
|
||||
copy of the nvmutil source code!
|
||||
|
||||
You may run this in your terminal:
|
||||
|
||||
make
|
||||
|
||||
This will result in a binary being created named `nvm`.
|
||||
Install this to wherever you want, such as `/usr/bin` (or
|
||||
whatever is in your `$PATH` for userspace programs).
|
||||
|
||||
TODO: Add `make install` to the Makefile, portably.
|
||||
|
||||
How to use nvmutil
|
||||
==================
|
||||
|
||||
You run it, passing as argument the path to a file, and you run
|
||||
commands on that file. This section will tell you how to
|
||||
perform various tasks, by using these commands.
|
||||
|
||||
In these examples, it is assumed that you have installed
|
||||
the `nvm` binary to somewhere in your `$PATH`. If you haven't
|
||||
done that, you could still run it in cwd for instance:
|
||||
|
||||
./nvm bla bla bla
|
||||
|
||||
Exit status
|
||||
-----------
|
||||
|
||||
The `nvmutil` program uses `errno` extensively. The best error
|
||||
handling is done this way, the Unix way. Error handling is extremely
|
||||
strict, in nvmutil; on program exit, the errno message is printed (if not
|
||||
zero) and the value of errno is returned (upon exit from `int main`).
|
||||
|
||||
The `main` function always returns `errno`, no matter what. This style
|
||||
of programming (set errno and return) is a very old fashioned way of
|
||||
doing things, and in many cases it is the most *correct* way.
|
||||
|
||||
This is why we say `zero status` and `non-zero status` in Unix
|
||||
programs, when we talk about exit status. Zero is success, and
|
||||
anything above zero is fail; errno is zero by default, unless
|
||||
set, and it will always be set to a value above zero (if set).
|
||||
|
||||
All commands (except `dump`) require read and write access. The `dump`
|
||||
command only requires read access on files. Where sufficient permission
|
||||
is not given (read and/or write), nvmutil will exit with non-zero status.
|
||||
|
||||
Non-zero status will also be returned, if the target file is *not*
|
||||
of size *8KB*.
|
||||
|
||||
Additional rules regarding exit status shall apply, depending on
|
||||
what command you use. Commands are documented in the following sections:
|
||||
|
||||
Change MAC address
|
||||
------------------
|
||||
|
||||
The `nvm` program lets you change the MAC address. It sets
|
||||
a valid checksum, after changing the MAC address. This program
|
||||
operates on *both* NVM parts, but it will only modify a given
|
||||
part if the existing checksum is correct. It will exit with zero
|
||||
status if at least one part is modified; otherwise, it will
|
||||
exit with non-zero status.
|
||||
|
||||
On release 20220808 and below, validation merely
|
||||
checks whether `xx:xx:xx:xx:xx:xx` is given, where each
|
||||
nibble is a hexademical number. On release 20220810 and above,
|
||||
the following additional rules are *also enforced*:
|
||||
|
||||
* User cannot specify multicast addresses
|
||||
* User cannot specify `00:00:00:00:00:00`
|
||||
* When generating random addresses, if the right
|
||||
most nibble of the left-most byte is `?` (random),
|
||||
nvmutil will (in code) force the generated MAC
|
||||
address to be local (not global), and will prevent
|
||||
a multicast address from being generated.
|
||||
|
||||
A multicast address is invalid because it represents
|
||||
multiple devices; you must specify a unicast address.
|
||||
A global address is one uniquely assigned by the vendor,
|
||||
and a local address is an overridden one. You *can* set
|
||||
global MAC addresses in nvmutil, for example if you are
|
||||
simply copying what was officially assigned to your NIC,
|
||||
you can do that. For example, if your MAC address
|
||||
was `00:de:ad:be:ef:69` as assigned by the manufacturer,
|
||||
which is a global unicast MAC address, you would type:
|
||||
|
||||
nvm gbe.bin setmac 00:de:ad:be:ef:69
|
||||
|
||||
How to use (the MAC address in just an example):
|
||||
|
||||
nvm gbe.bin setmac 00:de:ad:be:ef:00
|
||||
|
||||
You can also set random MAC addresses:
|
||||
|
||||
nvm gbe.bin setmac ??:??:??:??:??:??
|
||||
|
||||
In this example, every character is random. However, you
|
||||
can mix and match random characters with static ones. For
|
||||
example:
|
||||
|
||||
nvm gbe.bin setmac 00:1f:16:??:??:??
|
||||
|
||||
You can also pass it without a MAC address:
|
||||
|
||||
nvm gbe.bin setmac
|
||||
|
||||
If you only type `setmac` without specifying a MAC address,
|
||||
it will do the same thing as `setmac ??:??:??:??:??:??`. This
|
||||
behaviour is not present in 20220808, but is available in
|
||||
release 20220810 and above.
|
||||
|
||||
This will set the last three bytes randomly, while the
|
||||
MAC address would begin with `00:1f:16`.
|
||||
|
||||
The *reason* nvmutil doesn't alter a part with an existing
|
||||
invalid checksum, is precisely so that if the algorithm
|
||||
changes in future Intel PHYs, nvmutil will just fail and
|
||||
not modify your file. This is because the checksum would
|
||||
then be invalid, at all times. However, correct NVM parts
|
||||
with otherwise invalid checksums do exist, and can be
|
||||
corrected if you use the `setchecksum` command
|
||||
in `nvmutil`. It is common for vendor gbe files to contain
|
||||
one valid part and one invalid part, per checksum rules.
|
||||
|
||||
Verify checksums (and show MAC addresses)
|
||||
-----------------------------------------
|
||||
|
||||
This command *only* requires *read* access on files.
|
||||
|
||||
The `nvm` program can show a hexdump of both NVM parts, and
|
||||
tell you whether each one is valid (as per checksum calculation).
|
||||
It also prints the MAC address from each part.
|
||||
|
||||
How to use:
|
||||
|
||||
nvm gbe.bin dump
|
||||
|
||||
NOTE: This will exit with zero status if at least one part
|
||||
contains a valid checksum. If both parts are invalid, nvmutil
|
||||
will exit with non-zero status.
|
||||
|
||||
Copy part
|
||||
---------
|
||||
|
||||
This command requires read *and* write access on files.
|
||||
|
||||
The `nvm` program can copy one NVM part to another. It copies
|
||||
the *entire* 4KB part, within the 8KB file.
|
||||
|
||||
Overwrite part 0 with the contents of part 1:
|
||||
|
||||
nvm gbe.bin copy 1
|
||||
|
||||
Overwrite part 1 with the contents of part 0:
|
||||
|
||||
nvm gbe.bin copy 0
|
||||
|
||||
NOTE: If the part to be copied has a bad checksum, no operation
|
||||
will be performed, and nvmutil will exit with non-zero status.
|
||||
Otherwise, it will (if all other conditions are met) exit with
|
||||
zero status.
|
||||
|
||||
Swap parts
|
||||
----------
|
||||
|
||||
This command requires read *and* write access on files.
|
||||
|
||||
The `nvm` program can swap both 4KB parts in the GbE
|
||||
file. It does this, via simple XOR swaps.
|
||||
|
||||
How to use:
|
||||
|
||||
nvm gbe.bin swap
|
||||
|
||||
NOTE: This operation will be aborted if BOTH checksums
|
||||
are invalid. This is to guard against accidentally
|
||||
using `nvmutil` on the wrong file.
|
||||
|
||||
If *at least one* part is valid, nvmutil will return
|
||||
with zero exit status. If both parts are invalid, it will
|
||||
return non-zero.
|
||||
|
||||
Set valid checksum
|
||||
------------------
|
||||
|
||||
This command requires read *and* write access on files.
|
||||
|
||||
The `nvm` program can calculate and sets a valid checksum, on
|
||||
the desired NVM part. Usage:
|
||||
|
||||
Fix part 0:
|
||||
|
||||
nvm gbe.bin setchecksum 0
|
||||
|
||||
Fix part 1:
|
||||
|
||||
nvm gbe.bin setchecksum 1
|
||||
|
||||
*WARNING: NO validity checks are performed. This will simply
|
||||
set the checksum. There is no feasible way to guard against
|
||||
use on the wrong file, unlike with the other commands. Please
|
||||
make SURE you're running this on the correct file!*
|
||||
|
||||
Set invalid checksum
|
||||
--------------------
|
||||
|
||||
This command requires read *and* write access on files.
|
||||
|
||||
The `nvm` program can intentionally set an invalid checksum, on
|
||||
the desired NVM part. Usage:
|
||||
|
||||
Invalidate part 0:
|
||||
|
||||
nvm gbe.bin brick 0
|
||||
|
||||
Invalidate part 1:
|
||||
|
||||
nvm gbe.bin brick 1
|
||||
|
||||
NOTE: If the part already has an invalid checksum, no operation
|
||||
will be performed, and nvmutil will exit with non-zero status.
|
||||
This is to guard against `nvmutil` being used on the wrong file.
|
||||
|
||||
This may be desirable, if you've made modifications to both
|
||||
parts but you want to guarantee that only one of them is
|
||||
used. Also, the `setmac` command will only operate on
|
||||
parts that already have a valid checksum, so you could
|
||||
run `brick` before running `setmac` (or run it afterwards).
|
||||
|
||||
The Linux kernel's `e1000` driver will refuse to initialise
|
||||
Intel gigabit NICs that don't have a valid checksum. This
|
||||
is software-defined, and not enforced by the hardware.
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
The osboot project merged with Libreboot, and `nvmutil` was
|
||||
imported into the `lbmk` repository. A historical change log
|
||||
is included at [docs/install/nvmutilimport.md](nvmutilimport.md),
|
||||
but this simply lists historical changes to nvmutil when it
|
||||
was part of osboot. Future changes to nvmutil can be found by
|
||||
running `git log util/nvmutil` in `lbmk.git`. No more changes
|
||||
to `nvmutilimport.md` will be applied, but future releases of
|
||||
Libreboot announced in `news/` will mention any nvmutil changes.
|
||||
|
||||
The *older* `nvmutils` is still available, for reference. See:
|
||||
|
||||
* <https://notabug.org/osboot/nvmutils/>
|
||||
|
||||
The `nvmutil` software is a clean re-write of `nvmutils`,
|
||||
which is compiled to a single binary instead of multiple
|
||||
binaries. It contains many fixes and enhancements that
|
||||
are absent in the *original* `nvmutils` programs. The
|
||||
old `nvmutils` project has been deprecated, and
|
||||
abandoned. All new development shall now be performed
|
||||
on `nvmutil`.
|
||||
|
||||
Libreboot's version of nvmutil is located at `util/nvmutil` in
|
||||
the `lbmk.git` repository. The original nvmutil project, when
|
||||
it was part of osboot, is still available (for reference) here:
|
||||
|
||||
* <https://notabug.org/osboot/nvmutil/>
|
||||
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
This page is released under different copyright terms than most other pages
|
||||
on this website.
|
||||
|
||||
The `nvmutil` software and documentation are released under the following
|
||||
terms:
|
||||
|
||||
Copyright 2022 Leah Rowe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
Detailed revision history can be found in the Git repository; for code,
|
||||
look at `lbmk.git` and for documentation, look at `lbwww.git`.
|
||||
|
||||
Assimilation by Libreboot
|
||||
=========================
|
||||
|
||||
With no additional changes to nvmutil, the project became part of lbmk,
|
||||
which is the Libreboot build system. Please refer to Libreboot's imported
|
||||
version of the nvmutil documentation: [nvmutil.md](nvmutil.md)
|
||||
|
||||
This code and documentation import was performed on November 17th, 2022.
|
||||
|
||||
The notes below are for historical purposes, as they show versioned
|
||||
Change Logs from when nvmutil was part of osboot, but in its own
|
||||
repository. Post-osboot-libreboot-merge, it was decided that nvmutil
|
||||
shall now be part of the Libreboot build system proper.
|
||||
|
||||
Future changes to nvmutil (in `lbmk.git`) shall be included in regular
|
||||
Libreboot release announcements, under `news/`, so please be sure to
|
||||
check that from now on.
|
||||
|
||||
For historical and reference purposes, the original nvmutil repository
|
||||
shall be preserved on notabug. See:
|
||||
|
||||
<https://notabug.org/osboot/nvmutil>
|
||||
|
||||
nvmutil 20221106
|
||||
================
|
||||
|
||||
Very minor bugfix release:
|
||||
|
||||
* Pledge now changed to `stdio rpath` (instead of `stdio wpath`), only
|
||||
when the `dump` command is used. (pledge is only used on OpenBSD
|
||||
systems; an ifdef rule prevents its use on other systems)
|
||||
* Documentation inaccuracies fixed (pertaining to nvmutil exit statuses)
|
||||
* Documentation generally tidied up a bit
|
||||
|
||||
nvmutil 20221103
|
||||
================
|
||||
|
||||
Not much has changed, as this just fixes minor bugs and behavioural
|
||||
quirks seen in the previous release:
|
||||
|
||||
* Prototypes now fully declared, with variable names
|
||||
* Fix implicit type conversion in readFromFile()
|
||||
* Always exit with zero status if the file was successfully modified.
|
||||
Previously, nvmutil would exit non-zero if one of the parts was invalid,
|
||||
even if the other was OK (and successfully modified)
|
||||
* Always exit with zero status when running dump, if at least one
|
||||
part contained a valid checksum and the file is of the correct size,
|
||||
fully readable. Previously, nvmutil would exit non-zero if one or both
|
||||
checksums was correct, but it now only does this if both are invalid
|
||||
|
||||
nvmutil 20220828
|
||||
================
|
||||
|
||||
No new features have been added. This is a code cleanup and bugfix release.
|
||||
|
||||
* General code cleanup (e.g. simpler argument handling)
|
||||
* Do not print errno 0 (fixes error when using the libc in OpenBSD)
|
||||
* Improved errno handling
|
||||
* Endianness portability re-implemented
|
||||
* The `dump` command no longer warns about multicast MAC addresses
|
||||
(such a warning is unnecessary, and up to the user to prevent)
|
||||
* The `setmac` command still prevents multicast MAC addresses being
|
||||
set, but no longer specifically warns about them (the documentation
|
||||
says not to use them already. No need to re-implement documentation
|
||||
in code)
|
||||
* Bug fix: errno now set, when an invalid file size is detected. The
|
||||
previous nvmutil version would exit (no operation) when the file size
|
||||
was wrong, but it would return with zero status. It now returns with
|
||||
non-zero status
|
||||
* The compiled binary size is still roughly the same as in the last
|
||||
release; the endianness checks increase the size, but other optimizations
|
||||
were made (e.g. cleaner argument handling). Tested with tcc on an x86\_64
|
||||
machine, where a 0.16% binary size increase was observed.
|
||||
|
||||
nvmutil 20220815
|
||||
================
|
||||
|
||||
No new features have been added. This is a code cleanup and bugfix release.
|
||||
|
||||
* Further 7% reduction in binary size, compared to the previous release.
|
||||
This is tested with `tcc` in an x86\_64 machine. On my tests, `tcc`
|
||||
produces a 10540 byte binary in the previous release; in this release
|
||||
I got 9796 bytes.
|
||||
* It should be noted that `nvmmac` from the older nvmutils is 9892 bytes
|
||||
compiled with `tcc` on my test system; that's with the help/version
|
||||
output text removed from nvmmac. *This* nvmutil release contains
|
||||
so many more features and safety checks than just that lone `nvmmac`
|
||||
utility, yet the `nvmutil` binary is 1% smaller in size! That's how
|
||||
efficient the `nvmutil` code is, and there is probably room for further
|
||||
improvement of code efficiency.
|
||||
* Endianness portability code deleted; it was untested, and still is, so
|
||||
now nvmutil will detect the host endianness and exit, if the host is
|
||||
big endian (nearly all hosts these days are little endian, and it's
|
||||
very unlikely that you will use a big endian host).
|
||||
(the code will be properly tested and ported to big-endian hosts for the
|
||||
next release)
|
||||
* The `status` variable is no longer used; instead, `errno` is used
|
||||
exclusively and extensively. Error handling is much simpler, and much
|
||||
more unixy as a result.
|
||||
* Error messages are more terse
|
||||
* Fix build issues with clang, from the previous release
|
||||
* The `dump` command no longer states whether the MAC address is local
|
||||
or global; this can be easily done by yourself, and this change slightly
|
||||
reduces code bloat in nvmutil. The code still warns you if the MAC address
|
||||
is multicast
|
||||
|
||||
nvmutil 20220810
|
||||
================
|
||||
|
||||
* 3.4% reduction in binary size (as tested with tcc on x86\_64),
|
||||
due to code optimizations, *while* adding new checks and new features.
|
||||
* Random MAC address generation now takes multicast/unicast and
|
||||
local/global MAC addresses into account. The generator now *forces*
|
||||
local MAC addresses to be generated; the only way to set a global
|
||||
address is to set the corresponding nibble statically.
|
||||
Multicast and all-zero MAC addresses are *no longer permitted* in code.
|
||||
* The `dump` command now warns when the address is multicast, if set by
|
||||
another tool or older nvmutil that way (it will also return non-zero
|
||||
status upon exit). In addition, it will say whether the address is
|
||||
locally or globally assigned.
|
||||
* nvmutil now aborts when you try to open a directory
|
||||
* Even more terse error/feedback messages than in the last release,
|
||||
while still being friendly and informative
|
||||
* word/setWord now done in a more efficient, endian-specific way
|
||||
on x86\_64 platforms; if non-x86\_64, it falls back to the portable
|
||||
functions
|
||||
* The code has been simplified in general, and tidied up compared to
|
||||
the previous release
|
||||
* The `setmac` command can now be used without specifying a MAC address,
|
||||
which will cause the same behaviour as `setmac ??:??:??:??:??:??`
|
||||
|
||||
nvmutil 20220808
|
||||
================
|
||||
|
||||
Released on 8 August 2022. Changes:
|
||||
|
||||
* Vastly reduced binary size (21% reduction); the source line
|
||||
count has reduced by roughly the same amount (slightly higher
|
||||
than 21%, because of the extra stuff compilers add).
|
||||
This is *with* new features and behaviours added; the code
|
||||
is just that much more efficient, and I've thoroughly audited it.
|
||||
* OpenBSD `pledge(2)` now used, if available at build time
|
||||
(ifdef rule used, so it still compiles on Linux/FreeBSD)
|
||||
* New feature: `setmac` is now able to set *random* MAC addresses.
|
||||
This is done by reading from `/dev/urandom`. It is done
|
||||
conditionally, per-nibble, as specified by the user. For example,
|
||||
you can specify `??:??:??:??:??:??` and every nibble will be
|
||||
random, or you could set some of them statically. For
|
||||
example: `00:1f:16:??:4?:?2`
|
||||
* The `read()` and `pwrite()` functions are now used for reading
|
||||
and writing files; older nvmutil versions used fopen/fseek/ftell
|
||||
and so on. The read/write functions are POSIX, and enable
|
||||
more robust file handling.
|
||||
* On `showmac` and `dump`, `O_RDONLY` is now set when
|
||||
executing `read()`. This means that these commands can now be
|
||||
used on read-only files.
|
||||
* Makefile: `-Os` flag used, instead of `-O2`
|
||||
* Error messages and feedback are much more user-friendly,
|
||||
and useful in general, while being much more terse.
|
||||
* The returned status on exit is *much* stricter. For example,
|
||||
the `dump` command will always cause an `EXIT_FAILURE` status
|
||||
when at least *one* part in the NVM image has a bad checksum.
|
||||
When writing a new MAC address, it will *work* only on valid
|
||||
parts like before, but *now* nvmutil will return with `EXIT_FAILURE`
|
||||
if *one OR* both parts are bad; older nvmutil versions *always*
|
||||
returned `EXIT_SUCCESS` after modifying the file.
|
||||
* The `help` and `version` commands have been removed; it is
|
||||
best to simply read the documentation. Programs should not
|
||||
include documentation inside themselves, but documentation should
|
||||
always be supplied separately, alongside that program. This
|
||||
change alone accounts for roughly 1/3 (33%) of the code size
|
||||
reduction; the other 2/3 of that reduction is due to increased
|
||||
code efficiency in general.
|
||||
|
||||
Regarding code size reduction
|
||||
-----------------------------
|
||||
|
||||
My test setup is an x86\_64 machine with `tcc` used
|
||||
as the compiler; the libc doesn't really matter, if
|
||||
you use dynamic linking. Command:
|
||||
|
||||
make CC=tcc
|
||||
|
||||
Observations (dynamic linking with libc files):
|
||||
|
||||
* 20220808: 10.67KB
|
||||
* 20220802 (unmodified): 13.51KB
|
||||
* 20220802 (help/version command removed): 12.56KB
|
||||
|
||||
SLOC (source lines of code):
|
||||
|
||||
* 20220808: 321 lines
|
||||
* 20220802 (unmodified): 421 lines
|
||||
* 20220802 (help/version command removed): 373 lines
|
||||
|
||||
These numbers were obtained, using the `sloccount` program
|
||||
by David A. Wheeler, which you can find here:
|
||||
|
||||
* <https://dwheeler.com/sloccount/>
|
||||
|
||||
This means that the actual reduction in compiled *logic* is
|
||||
about 1.89KB, or a 15% reduction, in nvmutil 20220808. By *logic*,
|
||||
I mean all code excluding the help function; this distinction is
|
||||
important, because the help/version commands are unavailable in
|
||||
nvmutil 20220808, but they were available in nvmutil 20220802.
|
||||
|
||||
Extra note: I also tested compressed sizes. With `tar` piped to `xz -9e`,
|
||||
I saw: about 3KB if compiled with tcc, and 5KB using gcc. Clang
|
||||
produces binaries of similar size, when compared with GCC.
|
||||
|
||||
Since the performance of nvmutil is largely disk-bound, I really
|
||||
recommend compiling it with `tcc`, not GCC or Clang because the
|
||||
binary sizes are much larger with those compilers, even with
|
||||
optimization flags; despite this, the Makefile in nvmutil
|
||||
assumes GCC/Clang and sets `CFLAGS` to `-Os`.
|
||||
|
||||
nvmutil 20220802
|
||||
================
|
||||
|
||||
Released on 2 August 2022. Changes:
|
||||
|
||||
* Another major code cleanup
|
||||
* More reliable argument handling
|
||||
* Files now loaded *after* verifying arguments
|
||||
* Files no longer written unless all checks pass
|
||||
(files were previously written unconditionally, even
|
||||
if no changes were made, wasting disk i/o)
|
||||
* Makefile now explicitly declares CFLAGS
|
||||
(strictest flags possible, warnings treated as errors)
|
||||
* More secure handling of strings; strnlen used instead
|
||||
of strlen, strncmp used instead of strcmp, number of
|
||||
characters limited
|
||||
* New command added: show mac
|
||||
(show what mac addresses are stored in both parts)
|
||||
* More human-friendly messages and help text
|
||||
* help/version commands actually listed in help output
|
||||
|
||||
nvmutil 20220731
|
||||
================
|
||||
|
||||
Released on 31 July 2022. Changes:
|
||||
|
||||
* Major code cleanup
|
||||
* Most operations now abort, if being performed
|
||||
on invalid files.
|
||||
* More robust error handling
|
||||
* More user-friendly error messages
|
||||
* The `malloc` function is no longer used
|
||||
|
||||
That's it. Bug fixes and safety features added. Enjoy!
|
||||
|
||||
nvmutil 20220728
|
||||
================
|
||||
|
||||
Initial release. It is functionally equivalent to the
|
||||
older `nvmutils`, developed for the osboot project. This
|
||||
newer version is reduced to a single source file instead
|
||||
of many, and builds as a single binary instead of many.
|
|
@ -30,6 +30,9 @@ For example:
|
|||
|
||||
./blobutil inject -r t440p_libreboot.rom -b t440p_12mb -m 00:f6:f0:40:71:fd
|
||||
|
||||
NOTE: this makes use of `nvmutil`, which you can read more about in
|
||||
the [nvmutil documentation](nvmutil.md).
|
||||
|
||||
Splitting The Rom
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@ For example:
|
|||
|
||||
./blobutil inject -r x230_libreboot.rom -b x230_12mb -m 00:f6:f0:40:71:fd
|
||||
|
||||
NOTE: this makes use of `nvmutil`, which you can read more about in
|
||||
the [nvmutil documentation](nvmutil.md).
|
||||
|
||||
Splitting The Rom
|
||||
-----------------
|
||||
|
||||
|
|
Loading…
Reference in New Issue