Support booting with EFI.

This commit is contained in:
Jonas 'Sortie' Termansen 2023-11-27 23:12:52 +00:00
parent f2a2d24161
commit 2ee030f409
13 changed files with 328 additions and 37 deletions

View File

@ -325,7 +325,7 @@ esac
cat << EOF
hook_kernel_pre
echo -n "Loading /$kernel ($(human_size $kernel)) ... "
multiboot /$kernel \$no_random_seed \$enable_network_drivers \$chain "\$@"
multiboot /$kernel --firmware=\$grub_platform \$no_random_seed \$enable_network_drivers \$chain "\$@"
echo done
hook_kernel_post
# TODO: Injecting configuration doesn't work for mounted cdroms.

View File

@ -1,3 +1,3 @@
set_minimal="cut dash e2fsprogs grep grub libssl mdocml sed signify tar wget xargs xz"
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip irssi libcurl libcurses libstdc++ m4 make nano ntpd patch perl pkg-config python ssh texinfo vim xorriso"
set_minimal="cut dash dosfstools e2fsprogs grep grub grub-i386-pc grub-i386-efi grub-x86_64-efi libssl mdocml sed signify tar wget xargs xz"
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip irssi libcurl libcurses libstdc++ m4 make mtools nano ntpd patch perl pkg-config python ssh texinfo vim xorriso"
sets="basic minimal"

View File

@ -0,0 +1,8 @@
NAME=grub-i386-efi
EDITION=2
BUILD_LIBRARIES='libiconv? libintl? libfreetype? liblzma?'
SOURCE_PORT=grub
LICENSE=GPL-3.0-or-later
BUILD_SYSTEM=configure
CONFIGURE_ARGS='--disable-werror --program-prefix= --with-platform=efi --target=i686-sortix'
MAKE_ARGS='-C grub-core'

View File

@ -0,0 +1,9 @@
NAME=grub-i386-pc
EDITION=2
RENAMES="grub@1: grub-i386-pc@2"
BUILD_LIBRARIES='libiconv? libintl? libfreetype? liblzma?'
SOURCE_PORT=grub
LICENSE=GPL-3.0-or-later
BUILD_SYSTEM=configure
CONFIGURE_ARGS='--disable-werror --program-prefix= --with-platform=pc'
MAKE_ARGS='-C grub-core'

View File

@ -0,0 +1,9 @@
NAME=grub-x86_64-efi
EDITION=2
BUILD_LIBRARIES='libiconv? libintl? libfreetype? liblzma?'
SOURCE_PORT=grub
LICENSE=GPL-3.0-or-later
BUILD_SYSTEM=configure
# TODO: Unfortunately 32-bit sortix gcc fails due to no 64-bit support.
CONFIGURE_ARGS='--disable-werror --program-prefix= --with-platform=efi --target=x86_64-sortix'
MAKE_ARGS='-C grub-core'

View File

@ -253,6 +253,36 @@ diff -Paur --no-dereference -- grub.upstream/grub-core/lib/libgcrypt-grub/cipher
{
k[i >> 2][i & 3] = key[i];
}
diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/basic/platform.c grub/grub-core/osdep/basic/platform.c
--- grub.upstream/grub-core/osdep/basic/platform.c
+++ grub/grub-core/osdep/basic/platform.c
@@ -18,9 +18,25 @@
#include <grub/util/install.h>
+#ifdef __sortix__
+#include <sys/kernelinfo.h>
+
+#include <string.h>
+#endif
+
const char *
grub_install_get_default_x86_platform (void)
-{
+{
+#ifdef __sortix__
+ char firmware[16];
+ if (!kernelinfo("firmware", firmware, sizeof(firmware)) &&
+ !strcmp(firmware, "efi"))
+#ifdef __i386__
+ return "i386-efi";
+#else
+ return "x86_64-efi";
+#endif
+#endif
return "i386-pc";
}
diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/getroot.c grub/grub-core/osdep/getroot.c
--- grub.upstream/grub-core/osdep/getroot.c
+++ grub/grub-core/osdep/getroot.c
@ -564,6 +594,41 @@ diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/sortix/random.c gru
+ arc4random_buf(out, len);
+ return 0;
+}
diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/unix/config.c grub/grub-core/osdep/unix/config.c
--- grub.upstream/grub-core/osdep/unix/config.c
+++ grub/grub-core/osdep/unix/config.c
@@ -35,8 +35,7 @@
{
static char *value = NULL;
if (!value)
- value = grub_util_path_concat (3, GRUB_SYSCONFDIR,
- "default", "grub");
+ value = grub_util_path_concat (2, GRUB_SYSCONFDIR, "grub");
return value;
}
@@ -78,6 +77,10 @@
if (v && v[0] == 'y' && v[1] == '\0')
cfg->is_cryptodisk_enabled = 1;
+ v = getenv ("GRUB_REMOVABLE");
+ if (v && grub_strcmp (v, "true") == 0)
+ cfg->is_removable = 1;
+
v = getenv ("GRUB_DISTRIBUTOR");
if (v)
cfg->grub_distributor = xstrdup (v);
@@ -105,8 +108,8 @@
*ptr++ = *iptr;
}
- strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
- "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_DISTRIBUTOR\"");
+ strcpy (ptr, "'; printf \"GRUB_ENABLE_CRYPTODISK=%s\\nGRUB_REMOVABLE=%s\\nGRUB_DISTRIBUTOR=%s\\n\" "
+ "\"$GRUB_ENABLE_CRYPTODISK\" \"$GRUB_REMOVABLE\" \"$GRUB_DISTRIBUTOR\"");
argv[2] = script;
argv[3] = '\0';
diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/unix/getroot.c grub/grub-core/osdep/unix/getroot.c
--- grub.upstream/grub-core/osdep/unix/getroot.c
+++ grub/grub-core/osdep/unix/getroot.c
@ -640,6 +705,17 @@ diff -Paur --no-dereference -- grub.upstream/grub-core/osdep/unix/platform.c gru
bootnum = line + sizeof ("Boot") - 1;
bootnum[4] = '\0';
if (!verbosity)
diff -Paur --no-dereference -- grub.upstream/include/grub/emu/config.h grub/include/grub/emu/config.h
--- grub.upstream/include/grub/emu/config.h
+++ grub/include/grub/emu/config.h
@@ -36,6 +36,7 @@
struct grub_util_config
{
int is_cryptodisk_enabled;
+ int is_removable;
char *grub_distributor;
};
diff -Paur --no-dereference -- grub.upstream/include/grub/emu/getroot.h grub/include/grub/emu/getroot.h
--- grub.upstream/include/grub/emu/getroot.h
+++ grub/include/grub/emu/getroot.h
@ -670,6 +746,27 @@ diff -Paur --no-dereference -- grub.upstream/util/bash-completion.d/Makefile.in
bashcompletion_DATA = $(bash_completion_script)
all: all-am
diff -Paur --no-dereference -- grub.upstream/util/config.c grub/util/config.c
--- grub.upstream/util/config.c
+++ grub/util/config.c
@@ -42,6 +42,17 @@
cfg->is_cryptodisk_enabled = 1;
continue;
}
+ if (grub_strncmp (ptr, "GRUB_REMOVABLE=",
+ sizeof ("GRUB_REMOVABLE=") - 1) == 0)
+ {
+ ptr += sizeof ("GRUB_REMOVABLE=") - 1;
+ if (*ptr == '"' || *ptr == '\'')
+ ptr++;
+ if (grub_strncmp (ptr, "true", sizeof ("true") - 1) == 0)
+ cfg->is_removable = 1;
+ continue;
+ }
+
if (grub_strncmp (ptr, "GRUB_DISTRIBUTOR=",
sizeof ("GRUB_DISTRIBUTOR=") - 1) == 0)
{
diff -Paur --no-dereference -- grub.upstream/util/getroot.c grub/util/getroot.c
--- grub.upstream/util/getroot.c
+++ grub/util/getroot.c
@ -724,6 +821,76 @@ diff -Paur --no-dereference -- grub.upstream/util/grub-fstest.c grub/util/grub-f
root = alloc_root;
}
}
diff -Paur --no-dereference -- grub.upstream/util/grub-install.c grub/util/grub-install.c
--- grub.upstream/util/grub-install.c
+++ grub/util/grub-install.c
@@ -848,6 +848,9 @@
grub_util_load_config (&config);
+ if (config.is_removable)
+ removable = 1;
+
if (!bootloader_id && config.grub_distributor)
{
char *ptr;
@@ -860,7 +863,7 @@
if (!bootloader_id || bootloader_id[0] == '\0')
{
free (bootloader_id);
- bootloader_id = xstrdup ("grub");
+ bootloader_id = xstrdup ("sortix");
}
if (!grub_install_source_directory)
@@ -923,12 +926,20 @@
break;
}
+ if (!bootdir)
+ bootdir = grub_util_path_concat (3, "/", rootdir, GRUB_BOOT_DIR_NAME);
+
switch (platform)
{
case GRUB_INSTALL_PLATFORM_I386_PC:
case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
if (!install_device)
- grub_util_error ("%s", _("install device isn't specified"));
+ {
+ grub_devices = grub_guess_root_devices (bootdir);
+ if (!grub_devices || !grub_devices[0] ||
+ !(install_device = grub_util_get_os_disk (grub_devices[0])))
+ grub_util_error ("%s", _("install device isn't specified"));
+ }
break;
case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
if (install_device)
@@ -961,9 +972,6 @@
break;
}
- if (!bootdir)
- bootdir = grub_util_path_concat (3, "/", rootdir, GRUB_BOOT_DIR_NAME);
-
{
char * t = grub_util_path_concat (2, bootdir, GRUB_DIR_NAME);
grub_install_mkdir_p (t);
@@ -1803,6 +1811,7 @@
break;
case GRUB_INSTALL_PLATFORM_I386_EFI:
+#ifndef __sortix__
if (!efidir_is_mac)
{
char *dst = grub_util_path_concat (2, efidir, "grub.efi");
@@ -1810,6 +1819,7 @@
grub_install_copy_file (imgfile, dst, 1);
free (dst);
}
+#endif
/* Fallthrough. */
case GRUB_INSTALL_PLATFORM_X86_64_EFI:
if (efidir_is_mac)
diff -Paur --no-dereference -- grub.upstream/util/grub-mkconfig.in grub/util/grub-mkconfig.in
--- grub.upstream/util/grub-mkconfig.in
+++ grub/util/grub-mkconfig.in
@ -924,7 +1091,7 @@ diff -Paur --no-dereference -- grub.upstream/util/grub.d/10_sortix.in grub/util/
+ insmod part_$PARTMAP
+ insmod $FS
+ search --no-floppy --fs-uuid --set=root $HINTS_STRING $FS_UUID
+ multiboot $BOOT_REL/sortix.bin $GRUB_CMDLINE_SORTIX
+ multiboot $BOOT_REL/sortix.bin --firmware=\$grub_platform $GRUB_CMDLINE_SORTIX
+ module $OLD_BOOT_REL/random.seed --random-seed
+ module $BOOT_REL/sortix.initrd
+}

View File

@ -1,4 +1,6 @@
NAME=grub
EDITION=2
RENAMES="grub@1: grub@2"
BUILD_LIBRARIES='libiconv? libintl? libfreetype? liblzma?'
VERSION=1.0-rc1
DISTNAME=sortix-grub-$VERSION
@ -7,7 +9,8 @@ ARCHIVE=$DISTNAME.$COMPRESSION
SHA256SUM=82ac8faf257fb3476969a0b79a0b5fd53d4cdefb2e2aa5941381477e38c5f9c5
UPSTREAM_SITE=https://pub.sortix.org/sortix/toolchain
UPSTREAM_ARCHIVE=$ARCHIVE
LICENSE=GPL-3.0-or-later
BUILD_SYSTEM=configure
CONFIGURE_ARGS='--disable-werror --program-prefix='
CONFIGURE_ARGS='--disable-werror --program-prefix= --with-platform=none'
POST_INSTALL=../grub.post-install
VERSION_REGEX='([0-9]+\.[0-9]+(\.[0-9]+)*(-rc[0-9]+)?)'
VERSION_REGEX='([0-9]+\.[0-9]+(\.[0-9]+)*(-rc[0-9]+)?)

View File

@ -7,3 +7,6 @@ if [ ! -e "$TIX_INSTALL_DIR$PREFIX/share/grub/unicode.pf2" ]; then
[ -e /usr/share/grub/unicode.pf2 ] &&
cp /usr/share/grub/unicode.pf2 "$TIX_INSTALL_DIR$PREFIX/share/grub/unicode.pf2"
fi
rm -rf "$TIX_INSTALL_DIR$PREFIX/lib/grub/"*"-none"
rmdir --ignore-fail-on-non-empty "$TIX_INSTALL_DIR$PREFIX/lib/grub"
rmdir --ignore-fail-on-non-empty "$TIX_INSTALL_DIR$PREFIX/lib"

View File

@ -7,5 +7,6 @@ ARCHIVE=$DISTNAME.$COMPRESSION
SHA256SUM=0b423119a27a69d417bb67cd38ccfb03d2a7387706911ee04e5d3c3f50e3619b
UPSTREAM_SITE=https://pub.sortix.org/fork/signify
UPSTREAM_ARCHIVE=$ARCHIVE
LICENSE=ISC
BUILD_SYSTEM=makefile
VERSION_REGEX='([0-9]{4}-[0-9]{2}-[0-9]{2})'

View File

@ -36,7 +36,7 @@ installation.
.It
ATA or AHCI harddisk with at least 1 GiB of unpartitioned space.
.It
BIOS firmware, or UEFI firmware in legacy mode.
BIOS or EFI firmware.
.It
PS/2 keyboard/mouse firmware emulation to use those devices.
.It
@ -68,6 +68,9 @@ or
to copy the release physically onto a USB portable storage device.
If the target machine has a cdrom drive, you can burn the release to a cdrom.
Insert the installation medium in the computer and power it on.
If you have EFI firmware, you need to disable secure boot.
EFI boot is preferred over the legacy BIOS boot, but you can use whatever method
you prefer if your firmware supports it.
If needed, change the boot order in the firmware to prefer the installation
medium over any existing operating system installations.
.Pp
@ -241,14 +244,28 @@ The answer will default to yes if no existing partitions are found, or if an
existing Sortix installation is found that uses the provided bootloader; and
will otherwise default to no.
.Pp
The bootloader will be installed on the boot harddisk, which is the harddisk
containing the
On
.Sy EFI ,
the bootloader will be installed onto the EFI System Partition that you
mount as
.Pa /boot/efi .
EFI installations should accept the bootloader and then pick the default
bootloader through the firmware.
TODO: The bootloader is currently installed as the fallback
.Pa EFI/BOOT/BOOTX64.EFI
or
.Pa EFI/BOOT/BOOTIA32.EFI
paths which doesn't dual-boot very well with other operating systems.
.Pp
On
.Sy BIOS,
the bootloader will be installed on the boot harddisk, which is the
harddisk containing the
.Pa /boot
partition if any, and otherwise the harddisk containing the root filesystem.
.Pp
Single-boot configurations should use the offered bootloader.
Dual-boot configurations should refuse it and arrange for bootloading by other
means.
Single-boot BIOS configurations should use the offered bootloader.
Dual-boot BIOS configurations should refuse it and arrange for bootloading by
other means.
The installer will generate
.Pa /etc/grub.d/10_sortix.cache
which is a fragment of GRUB configuration that offers the menu option of running
@ -304,15 +321,17 @@ You can view all devices with the
command.
.Pp
If the current device does not already have a partition table, you can create a
.Xr mbr 7
or
.Xr gpt 7
or
.Xr mbr 7
partition table using the
.Sy mktable
command.
.Xr gpt 7
is the preferred choice for new partition tables as
.Xr mbr 7 has unfortunate limitations.
EFI installations should use
.Xr gpt 7 .
If you are dissatisfied with the current partition table, you can use
the
.Sy rmtable
@ -336,17 +355,44 @@ The
command removes a partition table entry and effectively deletes all data on the
partition.
.Pp
If you accepted the included bootloader, it will be installed on the boot
harddisk, which is the harddisk containing the
.Pa /boot
partition if any, and otherwise the harddisk containing the root filesystem.
If the boot harddisk uses the
.Xr gpt 7
partitioning scheme, then you must create a
If you accepted the included bootloader:
.Bl -bullet
.It
On
.Sy EFI
you need an
.Sy EFI System Partition
mounted at
.Pa /boot/efi .
It should be at least 16 MB to provide room for growth in future versions of the
operating system.
The partition is shared with other operating systems, enlargen it as required
if you wish to dual-boot other operating systems.
The minimum size is 1 MB, however this size is unsupported for operating system
upgrades and doesn't leave room for other operating systems.
.It
On
.Sy BIOS
with
.Sy GPT
you need a
.Sy biosboot
partition on the boot harddisk which is where the bootloader will be installed.
partition on the harddisk containing the
.Pa /boot
directory.
It should be at the start of the boot harddisk and a size of 1 MiB will be more
than sufficient.
.It
On
.Sy BIOS
with
.Sy MBR
you don't need any bootloader partition.
However, the bootloader will be installed unprotected in the unpartitioned
space before the first partition on the harddisk containing the
.Pa /boot
directory.
.El
.Pp
You need to make a partition containing the root filesystem mounted at
.Pa / .

View File

@ -69,11 +69,6 @@ const char* prompt_man_page = "installation";
static struct partition_table* search_bios_boot_pt(struct filesystem* root_fs)
{
char firmware[64];
if ( kernelinfo("firmware", firmware, sizeof(firmware)) != 0 )
return NULL;
if ( strcmp(firmware, "bios") != 0 )
return NULL;
struct blockdevice* bdev = root_fs->bdev;
while ( bdev->p )
bdev = bdev->p->parent_bdev;
@ -194,6 +189,10 @@ static bool should_install_bootloader_bdev(struct blockdevice* bdev)
static bool should_install_bootloader(void)
{
char firmware[16];
if ( !kernelinfo("firmware", firmware, sizeof(firmware)) &&
!strcmp(firmware, "efi") )
return true;
bool any_systems = false;
for ( size_t i = 0; i < hds_count; i++ )
{
@ -354,6 +353,9 @@ static void grub_hash_password(char* buffer, size_t buffer_size, const char* pw)
static const char* const ignore_kernel_options[] =
{
"--firmware=bios",
"--firmware=efi",
"--firmware=pc",
"--no-random-seed",
"--random-seed",
NULL,
@ -511,7 +513,12 @@ int main(void)
err(2, "chdir: %s", etc);
struct utsname uts;
uname(&uts);
if ( uname(&uts) < 0 )
err(1, "uname");
char firmware[16];
if ( kernelinfo("firmware", firmware, sizeof(firmware)) != 0 )
err(1, "kernelinfo");
struct conf conf;
conf_init(&conf);
@ -572,6 +579,7 @@ int main(void)
missing_program("fsck.ext2") |
missing_program("grub-install") |
missing_program("man") |
(!strcmp(firmware, "efi") && missing_program("mkfs.fat")) |
missing_program("sed") |
missing_program("xargs") )
{
@ -909,6 +917,7 @@ int main(void)
mktable_tip, devices_tip);
struct filesystem* root_filesystem = NULL;
struct filesystem* boot_filesystem = NULL;
struct filesystem* esp_filesystem = NULL;
struct filesystem* bootloader_filesystem = NULL;
bool not_first = false;
while ( true )
@ -951,6 +960,7 @@ int main(void)
}
root_filesystem = NULL;
boot_filesystem = NULL;
esp_filesystem = NULL;
bool cant_mount = false;
for ( size_t i = 0; i < mountpoints_used; i++ )
{
@ -976,6 +986,8 @@ int main(void)
root_filesystem = mnt->fs;
if ( !strcmp(mnt->entry.fs_file, "/boot") )
boot_filesystem = mnt->fs;
if ( !strcmp(mnt->entry.fs_file, "/boot/efi") )
esp_filesystem = mnt->fs;
}
if ( cant_mount )
continue;
@ -983,12 +995,13 @@ int main(void)
bootloader_filesystem = boot_filesystem ? boot_filesystem : root_filesystem;
assert(bootloader_filesystem);
if ( !strcasecmp(accept_grub, "yes") &&
!strcmp(firmware, "bios") &&
missing_bios_boot_partition(bootloader_filesystem) )
{
const char* where = boot_filesystem ? "/boot" : "root";
const char* dev = device_path_of_blockdevice(bootloader_filesystem->bdev);
assert(dev);
textf("You are a installing BIOS bootloader and the %s "
textf("You are installing a BIOS bootloader and the %s "
"filesystem is located on a GPT partition, but you haven't "
"made a BIOS boot partition on the %s GPT disk. Pick "
"biosboot during mkpart and make a 1 MiB partition.\n",
@ -1007,10 +1020,41 @@ int main(void)
continue;
text("Proceeding, but expect the installation to fail.\n");
}
else if ( !strcasecmp(accept_grub, "yes") &&
!strcmp(firmware, "efi") &&
!esp_filesystem )
{
textf("You are installing an EFI bootloader, but you haven't made "
"an EFI System Partition. Pick efi during mkpart and make a "
"partition and mount it as /boot/efi.\n");
char return_to_disked[10];
while ( true )
{
// TODO: Document autoinstall key.
prompt(return_to_disked, sizeof(return_to_disked),
"missing_esp_partition",
"Return to disked to make an EFI partition?", "yes");
if ( strcasecmp(accept_grub, "no") == 0 ||
strcasecmp(accept_grub, "yes") == 0 )
break;
}
if ( !strcasecmp(return_to_disked, "yes") )
continue;
text("Proceeding, but expect the installation to fail.\n");
}
// TODO: Verify the ESP is actually FAT and has the correct ID/GUID.
break;
}
text("\n");
if ( !strcmp(firmware, "efi") )
{
// TODO: Ask for GRUB_DISTRIBUTOR when FAT LFN is implemented and make
// GRUB_REMOVABLE optional.
install_configurationf("grub", "w", "GRUB_REMOVABLE=true\n");
}
textf("We are now ready to install %s %s. Take a moment to verify "
"everything is in order.\n", BRAND_DISTRIBUTION_NAME, VERSIONSTR);
text("\n");
@ -1022,7 +1066,7 @@ int main(void)
const char* where = mnt->entry.fs_file;
printf(" %-16s use as %s\n", devname, where);
}
if ( strcasecmp(accept_grub, "yes") == 0 )
if ( strcasecmp(accept_grub, "yes") == 0 && !strcmp(firmware, "bios") )
{
struct partition* bbp = search_bios_boot_partition(bootloader_filesystem);
if ( bbp )
@ -1118,8 +1162,7 @@ int main(void)
{
printf(" - Installing bootloader...\n");
execute((const char*[]) { "chroot", "-d", ".", "grub-install",
device_path_of_blockdevice(bootloader_filesystem->bdev), NULL },
"_eqQ");
NULL }, "_eqQ");
printf(" - Configuring bootloader...\n");
execute((const char*[]) { "chroot", "-d", ".", "update-grub", NULL },
"_eqQ");

View File

@ -523,6 +523,10 @@ int main(int argc, char* argv[])
if ( conf.grub )
{
// TODO: After releasing Sortix 1.1, remove the boot device operand.
// It's kept for now to allow a mixed port environment with a
// new base system and old grub when bootstrapping Sortix 1.1
// on Sortix 1.0.
char* boot_path = join_paths(target, "boot");
if ( !boot_path )
err(2, "malloc");
@ -534,12 +538,11 @@ int main(int argc, char* argv[])
err(2, "Failed to find device of filesystem: %s", boot_path);
close(boot_fd);
free(boot_path);
// TODO: A better design for finding the parent block device.
if ( is_partition_name(boot_device) )
*strrchr(boot_device, 'p') = '\0';
printf(" - Installing bootloader...\n");
execute((const char*[]) { "grub-install", boot_device,
NULL }, "ceqQ", target);
NULL }, "ceqQ", target);
free(boot_device);
}

View File

@ -913,8 +913,7 @@ int main(void)
if ( do_upgrade_bootloader )
{
printf(" - Installing bootloader...\n");
execute((const char*[]) { "chroot", "-d", ".", "grub-install",
bootloader_dev_path, NULL },
execute((const char*[]) { "chroot", "-d", ".", "grub-install", NULL },
"_eqQ");
printf(" - Configuring bootloader...\n");
execute((const char*[]) { "chroot", "-d", ".", "update-grub", NULL },