Compute the disk and partition GUIDs from the disk image itself (with GUIDs initially all-zero)

This allows us to have a deterministic build (given a fixed environment)
without having to rely on GIT (the .git is not copied in the Guix build
environment), and without having to rely on Guix (which previously had to
inject the input hash into the source tree).

Guix is therefore "only" responsible for ensuring that the build tools and
environment are fixed, but is not strictly necessary to have reproducible
builds.
This commit is contained in:
Georges Dupéron 2018-09-30 14:23:17 +02:00
parent 3b640e997d
commit e8349eb34c
4 changed files with 48 additions and 64 deletions

7
.gitignore vendored
View File

@ -5,9 +5,8 @@
/build/check_makefile
/build/check_makefile_targets
/build/check_makefile_w_arnings
/build/gpt_disk_guid
/build/gpt_partition_guid
/build/input-hash
/build/gpt_guid1
/build/gpt_guid2
/build/iso_files/boot/iso_boot.sys
/build/iso_files/os.zip
/build/makefile_built_directories
@ -88,6 +87,8 @@
/build/os.offsets.hex
/build/os.reasm
/build/os.reasm.asm
/build/os_with_guid_0
/build/os_with_guid_hash
/build/os.zip
/build/os.zip.adjusted
/build/test_pass/emu_bochs

View File

@ -70,8 +70,6 @@ ${bld}/makefile_w_arnings: | $${@D}
${built_files}: | $${@D}
${bld}/makefile_w_arnings: ${Makefiles}
test -e input-hash || printf "\033[1;31mWARNING: input-hash should be created by guix build.\033[m\n"
@unset MAKEFLAGS MAKELEVEL MAKE_TERMERR MFLAGS; \
make -n --warn-undefined-variables \
OS_FILENAME=${OS_FILENAME} \

View File

@ -51,9 +51,10 @@ built_files += ${os_filename} \
${bld}/os.hex_with_offsets \
${bld}/iso_files/os.zip \
${bld}/iso_files/boot/iso_boot.sys \
${bld}/input-hash \
${bld}/gpt_disk_guid \
${bld}/gpt_partition_guid \
${bld}/gpt_guid1 \
${bld}/gpt_guid2 \
${bld}/os_with_guid_0 \
${bld}/os_with_guid_hash \
${more_offset_dec} \
${more_offset_hex} \
@ -224,49 +225,27 @@ ${bld}/os.zip.adjusted: ${bld}/os.zip ${dep_bytes_zip_start} ${bld}/check_makefi
gdisk_pipe_commands_slowly=while read str; do echo "$$str"; printf "\033[1;33m%s\033[m\n" "$$str" >&2; sleep 0.01; done
.PHONY: force-input-hash
${bld}/input-hash: force-input-hash ${bld}/check_makefile
# input-hash must be a 33 (or more) character-long hexadecimal hash of the
# inputs. It can be used to generate UUIDs for the generated disk image, for
# example.
#
# We use `git log -1 --pretty=format:%H' to obtain the hash of the current
# commit as a fallback, but we do not have access to that information
# within a Guix build environment.
h=$$( cat input-hash \
|| git log -1 --pretty=format:%H \
|| echo 0000000000000000000000000000000000000000 \
); \
if test "$$h" != "$$(cat $@ || echo '')"; then \
echo "$$h" > "$@"; \
fi
# The last digit is 1, to distinguish the disk GUID from the partition GUID
${bld}/gpt_disk_guid: ${bld}/input-hash ${bld}/check_makefile
cat $< \
| sed -e 's/^\(.\{8\}\)\(.\{4\}\)\(.\{4\}\)\(.\{4\}\)\(.\{11\}\).*$$/\1-\2-\3-\4-\51/' \
# The last digit of guid1 is 1, for guid2 it's 2, and so on.
# This allows us to have a disk GUID which is different from the partition GUID
${bld}/gpt_guid%: ${bld}/os_with_guid_0 ${bld}/check_makefile
sha256sum $< \
| sed -e 's/^\(.\{8\}\)\(.\{4\}\)\(.\{4\}\)\(.\{4\}\)\(.\{11\}\).*$$/\1-\2-\3-\4-\5$*/' \
| tr '[:lower:]' '[:upper:]' \
> $@
# The last digit is 2, to distinguish the disk GUID from the partition GUID
${bld}/gpt_partition_guid: ${bld}/input-hash ${bld}/check_makefile
cat $< \
| sed -e 's/^\(.\{8\}\)\(.\{4\}\)\(.\{4\}\)\(.\{4\}\)\(.\{11\}\).*$$/\1-\2-\3-\4-\52/' \
| tr '[:lower:]' '[:upper:]' \
> $@
gpt_disk_guid=${bld}/gpt_guid1
gpt_partition_guid=${bld}/gpt_guid2
${os_filename}: ${bld}/os.32k ${bld}/os.iso ${bld}/os.fat12 ${bld}/os.zip.adjusted \
${bld}/gpt_disk_guid ${bld}/gpt_partition_guid \
${dep_bytes_header_32k_start} \
${dep_bytes_header_32k_size} \
${dep_bytes_fat12_start} \
${dep_bytes_fat12_size} \
${dep_bytes_gpt_mirror_start} \
${dep_bytes_gpt_mirror_end} \
${dep_sectors_fat12_start} \
${dep_sectors_fat12_size} \
${dep_bytes_zip_start} \
${bld}/check_makefile
${bld}/os_with_guid_0: ${bld}/os.32k ${bld}/os.iso ${bld}/os.fat12 \
${dep_bytes_header_32k_start} \
${dep_bytes_header_32k_size} \
${dep_bytes_fat12_start} \
${dep_bytes_fat12_size} \
${dep_bytes_gpt_mirror_start} \
${dep_bytes_gpt_mirror_end} \
${dep_sectors_fat12_start} \
${dep_sectors_fat12_size} \
${bld}/check_makefile
rm -f $@
# start with the .iso
cp ${bld}/os.iso $@
@ -296,8 +275,23 @@ ${os_filename}: ${bld}/os.32k ${bld}/os.iso ${bld}/os.fat12 ${bld}/os.zip.adjust
printf "1\nN\n"; \
printf "01\nY\nN\n"; \
printf "x\n"; \
printf "g\n$$(cat ${bld}/gpt_disk_guid)\n"; \
printf "c\n$$(cat ${bld}/gpt_partition_guid)\n"; \
printf "g\n00000000-0000-0000-0000-000000000000\n"; \
printf "c\n00000000-0000-0000-0000-000000000000\n"; \
printf "p\no\nw\nY\n") | ${gdisk_pipe_commands_slowly} | gdisk $@
${bld}/os_with_guid_hash: ${bld}/os_with_guid_0 \
${gpt_disk_guid} ${gpt_partition_guid} \
${bld}/check_makefile
cp $< $@
# gdisk commands:
# * eXpert mode,
# * Change partition GUID, the GUID itself,
# * change disk GUID, the GUID itself,
# * Print GPT, print prOtective MBR, Write, Proceed.
(if test "$$(uname -o)" = "Cygwin"; then printf "Y\n"; fi; \
printf "x\n"; \
printf "g\n$$(cat ${gpt_disk_guid})\n"; \
printf "c\n$$(cat ${gpt_partition_guid})\n"; \
printf "p\no\nw\nY\n") | ${gdisk_pipe_commands_slowly} | gdisk $@
# Inject MS-DOS newlines (CR+LF) and comments (":: ") in the GUID field of unused partition table entries,
# so that the part that is to be skipped by MS-DOS does not form a line longer than the MS-DOS maximum
@ -307,6 +301,10 @@ ${os_filename}: ${bld}/os.32k ${bld}/os.iso ${bld}/os.fat12 ${bld}/os.zip.adjust
printf "\r\n:: %02x" $$i | dd bs=1 seek=$$(( 1024 + ( ($$i) - 1) * 128 + 16)) count=7 conv=notrunc of=$@; \
printf "\r\n:: %02x" $$i | dd bs=1 seek=$$(( ${bytes_gpt_mirror_start} + ( ($$i) - 1) * 128 + 16)) count=7 conv=notrunc of=$@; \
done
${os_filename}: ${bld}/os_with_guid_hash ${bld}/os.zip.adjusted \
${dep_bytes_zip_start} \
${bld}/check_makefile
cp -f $< $@
# splice in zip at the end
set -x; dd skip=${bytes_zip_start} seek=${bytes_zip_start} bs=1 conv=notrunc if=${bld}/os.zip.adjusted of=$@
chmod a+x-w $@

View File

@ -25,14 +25,13 @@
(ice-9 popen)
(ice-9 rdelim)
(gnu packages version-control)
(gnu packages vim)
(gnu packages package-management)
(gnu packages assembly)
(gnu packages base)
(gnu packages mtools)
(gnu packages cdrom)
(gnu packages compression)
(gnu packages disk)
(gnu packages vim)
(gnu packages linux))
;; For faketime
@ -77,17 +76,6 @@
`(#:phases
(modify-phases %standard-phases
;; unpack ;; this phase is enabled
(add-after 'unpack 'compute-input-hash
(lambda* (#:key inputs #:allow-other-keys)
(invoke "sh" "-c"
(string-append
" guix hash -rx . --format=base32"
" | tr '[:lower:]' '[:upper:]'"
" | head -c 48"
" | base32 -d"
" | xxd -ps"
" | head -c 60"
" > input-hash"))))
;; patch-source-shebangs ;; this phase is enabled
(add-after 'patch-source-shebangs 'make-clean
(lambda* (#:key inputs #:allow-other-keys)
@ -112,8 +100,6 @@
(list "in-guix" ,makefile-commit-timestamp)))
(native-inputs
`(("git" ,git)
("xxd" ,xxd)
("guix" ,guix)
("nasm" ,nasm)
("which" ,which)
("mtools" ,mtools)
@ -121,6 +107,7 @@
("zip" ,zip)
("faketime" ,faketime)
("gdisk" ,gptfdisk)
("xxd" ,xxd)
("column" ,util-linux)))
(description "Test framework to run an OS in multiple emulators, as a guest graphical / text shell on linux, and so on.")
(home-page "https://github.com/jsmaniac/os-test-framework")