]> git.ipfire.org Git - people/ms/bricklayer.git/commitdiff
bricklayer-master: Experimentally install GRUB on CD
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 12 May 2021 12:05:35 +0000 (12:05 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 12 May 2021 12:05:35 +0000 (12:05 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/bricklayer-master

index 4d1158f4da56b7c328c33eeb4bf95a4f7c78a751..6736c02c167471a0bf0e41928d16c010644eebf7 100644 (file)
 #                                                                             #
 ###############################################################################
 
+# Pakfire configuration file
+PAKFIRE_CONFIG="/etc/pakfire/distros/ipfire3.conf"
+
+# Packages to install in the live system
+PACKAGES=(
+       "@Base"
+       "kernel"
+)
+
+# Compress as best as we can
+ZSTD_COMPRESSION_LEVEL=22
+
+# Grub modules to install
+GRUB_MODULES=(
+       biosdisk
+       iso9660
+       linux
+       linux16
+       normal
+       search
+)
+
+allocate_file() {
+       local path="${1}"
+       local size="${2}"
+
+       dd if=/dev/zero of="${path}" bs=1k count="${size}"
+}
+
+make_live_system_image() {
+       local filename="${1}"
+
+       local tempdir="$(mktemp -d)"
+
+       # Install a very basic system
+       # XXX --arch="${arch}"
+       if ! pakfire --config="${PAKFIRE_CONFIG}" --root="${tempdir}" \
+                       install --without-recommends "${PACKAGES[@]}"; then
+               echo "Could not install live system" >&2
+               rm -rf "${tempdir}"
+               return 1
+       fi
+
+       # Create a squashfs image
+       if ! mksquashfs "${tempdir}" "${filename}" \
+                       -comp zstd -Xcompression-level "${ZSTD_COMPRESSION_LEVEL}"; then
+               rm -rf "${tempdir}"
+               return 1
+       fi
+
+       # Cleanup
+       rm -rf "${tempdir}"
+       return 0
+}
+
+make_boot_catalog() {
+       local path="${1}"
+
+       allocate_file "${path}" 2
+}
+
+make_grub_bios_image() {
+       local path="${1}"
+
+       local core_img="$(mktemp)"
+
+       # Create a standalone image
+       if ! grub-mkstandalone \
+                       --format="${grub_arch}-pc" \
+                       --output="${core_img}" \
+                       --modules="${GRUB_MODULES[@]}" \
+                       --install-modules="${GRUB_MODULES[@]}" \
+                       --fonts="" --locales=""; then
+               unlink "${core_img}"
+               return 1
+       fi
+
+       # Append cdboot.img with the generated core.img
+       if ! cat "/usr/lib/grub/${grub_arch}-pc/cdboot.img" "${core_img}" > "${path}"; then
+               unlink "${core_img}" "${path}"
+               return 1
+       fi
+
+       # Cleanup
+       unlink "${core_img}"
+
+       return 0
+}
+
+make_grub_efi_image() {
+       local path="${1}"
+
+       # Allocate file
+       if ! allocate_file "${path}" 2880; then
+               return 1
+       fi
+
+       # Format it with FAT
+       if ! mkdosfs -F 12 -n "BRICKLAYER_EFI" "${path}"; then
+               echo "Could not format the EFI filesystem" >&2
+               return 1
+       fi
+
+       local tempdir="$(mktemp -d)"
+
+       # Mount the disk
+       if ! mount -o loop "${path}" "${tempdir}"; then
+               echo "Could not mount EFI filesystem" >&2
+               return 1
+       fi
+
+       mkdir -p "${tempdir}/EFI/BOOT"
+
+       # Generate a GRUB image
+       if ! grub-mkstandalone \
+                       --format="${grub_arch}-efi" \
+                       --output="${tempdir}/EFI/BOOT/bootx64.efi" \
+                       --fonts="" --locales=""; then
+               echo "Could not generate GRUB EFI image" >&2
+               umount "${tempdir}"
+               rm -rf "${tempdir}"
+               return 1
+       fi
+
+       if ! umount "${tempdir}"; then
+               rm -rf "${tempdir}"
+               return 1
+       fi
+
+       return 0
+}
+
 mkimage() {
        local filename="${1}"
        local r=0
@@ -26,20 +158,28 @@ mkimage() {
        # Create a temporary working directory
        local tempdir="$(mktemp -d)"
 
+       # Create a directory for all the boot stuff
+       mkdir -p "${tempdir}/boot"
+
        # Create argument list for xorriso
        local args=(
                # Emulate running as mkisofs
                -as mkisofs
 
+               # Generate Joilet directory information
+               -J
+
+               # Generate rationalized Rock Ridge directory information
+               -r
+
                # Be less verbose
-               -quiet
+               #-quiet
 
                # The name of the volume
                -volid "${name}"
 
+               # Set ISO9660 conformance level
                -iso-level 3
-               -eltorito-alt-boot
-               -no-emul-boot
 
                # Where to write the output to?
                -output "${filename}"
@@ -48,13 +188,68 @@ mkimage() {
                "${tempdir}"
        )
 
-       # Append EFI arguments
-       if [ "${efi}" = "true" ]; then
+       # Determine GRUB architecture
+       local grub_arch="${arch}"
+       case "${arch}" in
+               aarch64)
+                       grub_arch="arm64"
+                       ;;
+
+               x86_64)
+                       grub_arch="i386"
+                       ;;
+       esac
+
+       # Generate GRUB BIOS image
+       if [ "${has_bios_boot}" = "true" ]; then
+               if ! make_grub_bios_image "${tempdir}/boot/biosboot.img"; then
+                       rm -rf "${tempdir}"
+                       return 1
+               fi
+
+               # Make boot catalog
+               if ! make_boot_catalog "${tempdir}/boot/boot.catalog"; then
+                       rm -rf "${tempdir}"
+                       return 1
+               fi
+
+               # Append to xorriso command line
+               args+=(
+                       -no-emul-boot
+                       -boot-load-size 4
+                       -boot-info-table
+                       -b "boot/biosboot.img"
+                       -c "boot/boot.catalog"
+
+                       # Enable hybrid boot mode
+                       --grub2-boot-info
+                       --grub2-mbr "/usr/lib/grub/${grub_arch}-pc/boot_hybrid.img"
+               )
+       fi
+
+       # Generate GRUB EFI image
+       if [ "${has_efi_boot}" = "true" ]; then
+               if ! make_grub_efi_image "${tempdir}/boot/efiboot.img"; then
+                       rm -rf "${tempdir}"
+                       return 1
+               fi
+
+               # Append to xorriso command line
                args+=(
-                       -e "EFI/efiboot.img"
+                       -eltorito-alt-boot
+                       -e "boot/efiboot.img"
+                       -no-emul-boot
+                       -isohybrid-gpt-basdat
                )
        fi
 
+       # Create the live system image
+       if ! make_live_system_image "${tempdir}/live-os.img"; then
+               rm -rf "${tempdir}"
+               return 1
+       fi
+
+       # Master the ISO file
        if ! xorriso "${args[@]}"; then
                r=1
        fi
@@ -67,7 +262,6 @@ mkimage() {
 
 main() {
        local arch="$(uname -m)"
-       local efi="true"
        local filename
 
        while [ $# -gt 0 ]; do
@@ -76,10 +270,6 @@ main() {
                                arch="${1#*=}"
                                ;;
 
-                       --disable-efi)
-                               efi="false"
-                               ;;
-
                        *.iso)
                                if [ -n "${filename}" ]; then
                                        echo "Filename has already been set" >&2
@@ -103,9 +293,30 @@ main() {
                return 2
        fi
 
+       local has_bios_boot="false"
+       local has_efi_boot="false"
+
+       # Configure some architecture-dependent environment variables
+       case "${arch}" in
+               aarch64)
+                       has_efi_boot="true"
+                       ;;
+
+               x86_64)
+                       has_bios_boot="true"
+                       #has_efi_boot="true"
+                       ;;
+
+               # Throw an error on unhandled architectures
+               *)
+                       echo "Unknown architecture: ${arch}" >&2
+                       return 2
+                       ;;
+       esac
+
        # Make image and delete it if something went wrong
        if ! mkimage "${filename}"; then
-               unlink "${filename}"
+               rm -f "${filename}"
                return 1
        fi