Go to file
Denis 'GNUtoo' Carikli 4c3de49fbb
guix: gnuboot-trisquel-preseed.img: Make it reproducible.
The "4.7 Mcopy" section inside the mtools info manual explains that
mcopy's '-m' argument "Preserve the file modification time.".

So in the commit 9cc02ddde1 ("packages:
roms: Start adding automatic tests."), I vaguely recall having used it
to workaround some reproducibility issues.

Guix 1.4.0 uses mtools 4.0.42. So after retrieving the source with
'guix time-machine --commit=v1.4.0 -- build --system=i686-linux
--source mtools' we have that in the writeit function in mcopy.c (with
arg->preserveTime being set by -m):
	/* preserve mod time? */
	if (arg->preserveTime)
		now = date;
	else
		getTimeNow(&now);

And date is set by the following in mtools 4.0.42:
	if (Source->Class->get_data(Source, &date, &filesize,
				    &type, 0) < 0 ){
		fprintf(stderr, "Can't stat source file\n");
		return -1;
	}

Since Guix is supposed to make images reproducible somehow, and that
mtools isn't patched by Guix to do that, and that it takes the time
from the source file, I used '-m'.

Since I was confident enough that gnuboot-trisquel-preseed.img was
reproducible, in the commit 9cc02ddde1
("packages: roms: Start adding automatic tests."), I also added the
checksum and checked it at build time to make sure the image is really
reproducible.

But when building this image again few days ago the checksum was
different. So I used the Guix diffoscope package to investigate the
issue.

Note that at the time of writing, you either need to use Guix's
diffoscope or to disable guestfs support in diffoscope for it to work,
otherwise diffoscope 277-1 (the version in the Parabola at the time of
writing) produce a python error probably because the partition table
size is 0, and it contains a FAT12 filesystem according to fdisk, but
then the FAT12 filesystem contained within also contains that
partition table. See the upstream bugreport at
https://salsa.debian.org/reproducible-builds/diffoscope/-/issues/390
for more details.

Here the preseed.img.old file corresponds to the checksum in the
commit 9cc02ddde1 ("packages: roms:
Start adding automatic tests."), and preseed.img.new to the one I got
by building again few days ago:
    $ sha512sum preseed.img.old preseed.img.new
    f12a4a941afc9e24288481ed1b44fbfedf52d706e9e8aa01cfb26bf5ccd54ca52afe9ef5497faf2966ba730c1200d8b8691ebb87e6a75cd8966e0edd49bcb3c0  preseed.img.old
    5613d9a5cdd8847d5a688d56c77b8cf8881baa5eef7f373bb05a5ec601e383204e6a57b399d3de913c29386b18e7e3903c9511037922204744e3234cadc8671b  preseed.img.new

And by using diffoscope we have:
    $ diffoscope preseed.img.old preseed.img.new
    --- preseed.img.old
    +++ preseed.img.new
    │┄ Format-specific differences are supported for ext2/ext3/ext4/btrfs/fat filesystems but no file-specific differences were detected; falling back to a binary diff. file(1) reports: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, root entries 512, sectors 2048 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 2, sectors/track 16, serial number 0x1234abcd, label: "MEDIA      ", FAT (12 bit)
    │┄ Installing the 'guestfs' Python module may produce a better output.
    @@ -157,23 +157,23 @@
     000009c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     000009d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     000009e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     000009f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000a00: 4d45 4449 4120 2020 2020 2008 0000 5a4b  MEDIA      ...ZK
     00000a10: 6e46 6e46 0000 5a4b 6e46 0000 0000 0000  nFnF..ZKnF......
     00000a20: 5052 4553 4545 4420 4346 4720 1800 0000  PRESEED CFG ....
    -00000a30: 21ec 21ec 0000 0000 21ec 0200 f50d 0000  !.!.....!.......
    +00000a30: 21ec 2859 0000 0000 21ec 0200 f50d 0000  !.(Y....!.......
     00000a40: 4365 0000 00ff ffff ffff ff0f 0000 ffff  Ce..............
     00000a50: ffff ffff ffff ffff ffff 0000 ffff ffff  ................
     00000a60: 0272 002d 0062 006f 006f 000f 0000 7400  .r.-.b.o.o....t.
     00000a70: 2e00 7300 6500 7200 7600 0000 6900 6300  ..s.e.r.v...i.c.
     00000a80: 0173 0068 0075 0074 0064 000f 0000 6f00  .s.h.u.t.d....o.
     00000a90: 7700 6e00 2d00 6100 6600 0000 7400 6500  w.n.-.a.f...t.e.
     00000aa0: 5348 5554 444f 7e31 5345 5220 0000 0000  SHUTDO~1SER ....
    -00000ab0: 21ec 21ec 0000 0000 21ec 0400 3002 0000  !.!.....!...0...
    +00000ab0: 21ec 2859 0000 0000 21ec 0400 3002 0000  !.(Y....!...0...
     00000ac0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000ad0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000ae0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000af0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000b00: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000b10: 0000 0000 0000 0000 0000 0000 0000 0000  ................
     00000b20: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Here it really look like a timestamp, and since mdir gave no
difference between the 2 files inside the 2 images, I patched mdir
with the following patch:
@@ -438,6 +438,18 @@ static int list_file(direntry_t *entry, MainParam_t *mp UNUSEDP)
                if(*mdir_longname)
                        printf(" %s", mdir_longname);
                printf("\n");
+
+               printf("-> ctime_ms: 0x%hhx\n", entry->dir.ctime_ms);
+               printf("-> ctime[0]: 0x%hhx\n", entry->dir.ctime[0]);
+               printf("-> ctime[1]: 0x%hhx\n", entry->dir.ctime[1]);
+               printf("-> cdate[0]: 0x%hhx\n", entry->dir.cdate[0]);
+               printf("-> cdate[1]: 0x%hhx\n", entry->dir.cdate[1]);
+               printf("-> adate[0]: 0x%hhx\n", entry->dir.adate[0]);
+               printf("-> adate[1]: 0x%hhx\n", entry->dir.adate[1]);
+               printf("-> time[0]: 0x%hhx\n", entry->dir.time[0]);
+               printf("-> time[1]: 0x%hhx\n", entry->dir.time[1]);
+               printf("-> date[0]: 0x%hhx\n", entry->dir.date[0]);
+               printf("-> date[1]: 0x%hhx\n", entry->dir.date[1]);
        } else {
                char tmp[4*MAX_VNAMELEN+1];

And this then gives  the following diff:
 -> ctime[1]: 0x0
 -> cdate[0]: 0x21
 -> cdate[1]: 0xec
--> adate[0]: 0x21
--> adate[1]: 0xec
+-> adate[0]: 0x28
+-> adate[1]: 0x59
 -> time[0]: 0x0
 -> time[1]: 0x0
 -> date[0]: 0x21
@@ -20,8 +20,8 @@
 -> ctime[1]: 0x0
 -> cdate[0]: 0x21
 -> cdate[1]: 0xec
--> adate[0]: 0x21
--> adate[1]: 0xec
+-> adate[0]: 0x28
+-> adate[1]: 0x59
 -> time[0]: 0x0
 -> time[1]: 0x0
 -> date[0]: 0x21

This means that the access date difers. This also explains why it was
not spoted during the creation of the commit
9cc02ddde1 ("packages: roms: Start
adding automatic tests.") as tests were done at the same date.

So this time I created a build VM by adding the following service to
my Guix system configuration (I also had to remove hacks I had that
set the kvm group id to the same ID used by Trisquel run 'guix system
reconfigure' and rebooted):
    (service virtual-build-machine-service-type
            (virtual-build-machine
             (cpu "host")
             (cpu-count 2)
             (auto-start? #f)))

This created a VM whose clock is set to 'a few years ago' according to
the Guix manual[1].

[1]https://guix.gnu.org/manual/devel/en/html_node/Virtualization-Services.html#Virtual-Build-Machines

I then ran built the image as usual:
    $ guix time-machine --commit=v1.4.0 -- build -L resources/guix/ \
      gnuboot-trisquel-preseed.img
      --without-tests=gnuboot-trisquel-preseed.img

I then copied the resulting image, started the build VM with 'herd
start build-vm', deleted the old image from the store (with 'guix gc
-D') and then re-built it (it used the VM to offload the build as
shown in the build logs).

And now both resulting files are now the same despite being built on a
different date.

See also the following blog post for more context into use cases for
this build VM[2]:

[2]https://hpc.guix.info/blog/2024/03/adventures-on-the-quest-for-long-term-reproducible-deployment/

Bug: https://savannah.gnu.org/bugs/?66224
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
Acked-by: Adrien 'neox' Bourmault <neox@gnu.org>
2024-10-05 11:05:39 +02:00
contrib Add contrib script to start the guix-daemon in chroots of systemd distros. 2024-09-08 17:28:22 +02:00
resources guix: gnuboot-trisquel-preseed.img: Make it reproducible. 2024-10-05 11:05:39 +02:00
tests packages: roms: Start adding automatic tests. 2024-09-08 17:11:04 +02:00
website website/docs/build: mark the Trisquel bug as solved and clarify the Guix one 2024-09-09 17:04:53 +02:00
.gitignore website: Remove news generation. 2024-09-08 17:37:11 +02:00
COPYING libreboot! 2021-05-18 13:56:12 +01:00
Makefile.am packages: roms: Start adding automatic tests. 2024-09-08 17:11:04 +02:00
README.md README.md: fix typo, add linebreak 2023-12-06 17:33:03 +01:00
autogen.sh Add topdir ./configure. 2024-05-12 22:56:04 +02:00
build build system: wrap git commands. 2024-09-08 17:18:53 +02:00
configure.ac Fix 'Git error: unable to parse OID - contains invalid characters' issue. 2024-09-08 17:17:15 +02:00
download build system: wrap git commands. 2024-09-08 17:18:53 +02:00
modify ./modify: enable to mask tasks. 2023-12-09 15:59:04 +01:00
projectname Continue Libreboot under the GNU project 2023-08-22 21:13:26 +02:00
update ./update: enable to mask tasks. 2023-12-09 15:59:37 +01:00

README.md

GNU Boot

This software is part of the GNU Project.

To load an operating system, computers need to be able to access storage devices (like an HDD or SSD) where the operating system is installed. They need RAM to work to load part of the operating system in RAM. Users also expect the display and keyboard to work before the operating system is loaded.

But on most computers, software is needed to initialize the RAM, the storage devices, the graphic card, to load the operating system, and give some information to the operating system on what hardware it is running on.

Because of that computers usually require boot software that is bundled in the computer. It is usually found on a very small storage chip that is inside the mainboard. That software is specific to a given computer.

Unfortunately that software is usually nonfree and GNU boot aims to replace that with 100% free software.

Like with other type of software, the fact that it is nonfree has real impacts. For instance this software often continues to run once the operating system is loaded and as it loads the operating system it can also modify it.

So having a nonfree boot software make it impossible for users to really trust their computers. Another common issue is that some BIOS/UEFI add restrictions to prevent users from replacing the WiFi card for instance. There are many more issues but listing them all here would make this description too long.

To replace nonfree boot software, GNU boot reuses various software projects (like Coreboot, U-boot, GRUB, SeaBIOS, etc), configure and build them to produce an image that can be installed to replace the nonfree boot software for specific computers.

Users can also do all that without GNU Boot but that tend to be complicated. Having a free software project that does all that enable people to collaborate on making sure that computers boot fine regardless of the upstream project status, for instance by making binary releases and collaborating to test them.

In addition GNU boot also comes with extensive documentation to make it as easy as possible to install GNU Boot and to empower users to modify the way their computer boot.

Since not all the project it reuses are 100% free software it also removes all the nonfree software found in them along the way and will also make the scripts and/or data that does that reusable for distributions or users that want to build their own free boot software without reusing the GNU Boot configuration or build system.

Not a coreboot fork!

GNU Boot is not a fork of coreboot, but more a boot firmware distribution including a modified version of coreboot, and other software like SeaBIOS, GRUB or u-boot.

Coreboot is not entirely free software as it includes binary blobs in it for some platforms. What GNU Boot does is download several revisions of coreboot, for different boards, and de-blob those coreboot revisions. This is done using the linux-libre deblob scripts, to find binary blobs in coreboot.

All new coreboot development should be done in coreboot (upstream), not GNU Boot. For example, if you wanted to add a new board to GNU Boot, you should add it to coreboot first. GNU Boot would then receive your code at a later date, when it updates itself.

The deblobbed coreboot tree used in GNU Boot is referred to as coreboot-libre, to distinguish it as a component of GNU Boot.

How this project came to exist

We believe computer users deserve to control all the software they run. This belief is the key principle of the Free Software Movement, and was the motive for developing the GNU operating system and starting the Free Software Foundation. We believe computer user freedom is a crucial human rights.

Unfortunately, such a muddle happened last year with a boot program that was free software and was called Libreboot: the development team added nonfree code to it, but continued to refer to it misleadingly as “Libreboot”.

Libreboot was first released in 2013. It has been widely recommended in the free software community for the last nine years. In November 2022, “Libreboot” began to include non-libre code. We have made repeated efforts to continue collaboration with those developers to help their version of Libreboot remain libre, but that was not successful.

Now weve stepped forward to stand up for freedom, ours and that of the wider community, by maintaining our own version a genuinely libre boot distribution: GNU Boot.

LICENSE FOR THIS README: GNU Free Documentation License 1.3 as published by the Free Software Foundation, with no invariant sections, no front cover texts and no back cover texts. If you wish it, you may use a later version of the GNU Free Documentation License as published by the Free Software Foundation.

Copy of the GNU Free Documentation License v1.3 here: https://www.gnu.org/licenses/fdl-1.3.en.html

Info about Free Software Foundation: https://www.fsf.org/