Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package grub2 for openSUSE:Factory checked in at 2022-03-08 20:31:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grub2 (Old) and /work/SRC/openSUSE:Factory/.grub2.new.2349 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grub2" Tue Mar 8 20:31:17 2022 rev:260 rq:959763 version:2.06 Changes: -------- --- /work/SRC/openSUSE:Factory/grub2/grub2.changes 2022-02-15 23:57:02.496172974 +0100 +++ /work/SRC/openSUSE:Factory/.grub2.new.2349/grub2.changes 2022-03-11 11:43:55.418786429 +0100 @@ -1,0 +2,18 @@ +Fri Mar 4 03:37:40 UTC 2022 - Michael Chang <mch...@suse.com> + +- Support saving grub environment for POWER signed grub images (jsc#SLE-23854) + * 0001-Add-grub_envblk_buf-helper-function.patch + * 0002-Add-grub_disk_write_tail-helper-function.patch + * 0003-grub-install-support-prep-environment-block.patch + * 0004-Introduce-prep_load_env-command.patch + * 0005-export-environment-at-start-up.patch +- Use enviroment variable in early boot config to looking up root device + * grub2.spec + +------------------------------------------------------------------- +Tue Mar 1 08:55:57 UTC 2022 - Michal Suchanek <msucha...@suse.com> + +- Remove obsolete openSUSE 12.2 conditionals in spec file +- Clean up powerpc certificate handling. + +------------------------------------------------------------------- New: ---- 0001-Add-grub_envblk_buf-helper-function.patch 0002-Add-grub_disk_write_tail-helper-function.patch 0003-grub-install-support-prep-environment-block.patch 0004-Introduce-prep_load_env-command.patch 0005-export-environment-at-start-up.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grub2.spec ++++++ --- /var/tmp/diff_new_pack.BGjWvK/_old 2022-03-11 11:43:57.490788753 +0100 +++ /var/tmp/diff_new_pack.BGjWvK/_new 2022-03-11 11:43:57.494788757 +0100 @@ -53,11 +53,9 @@ %endif BuildRequires: xz-devel %ifarch x86_64 aarch64 ppc ppc64 ppc64le -%if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110 BuildRequires: openssl >= 0.9.8 BuildRequires: pesign-obs-integration %endif -%endif %if 0%{?suse_version} >= 1210 # Package systemd services files grub2-once.service BuildRequires: systemd-rpm-macros @@ -353,6 +351,11 @@ Patch834: 0022-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch Patch835: 0023-x509-allow-Digitial-Signature-plus-other-Key-Usages.patch Patch836: 0001-grub-install-Add-SUSE-signed-image-support-for-power.patch +Patch837: 0001-Add-grub_envblk_buf-helper-function.patch +Patch838: 0002-Add-grub_disk_write_tail-helper-function.patch +Patch839: 0003-grub-install-support-prep-environment-block.patch +Patch840: 0004-Introduce-prep_load_env-command.patch +Patch841: 0005-export-environment-at-start-up.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -638,7 +641,7 @@ GRUB_MODULES="${CD_MODULES} ${FS_MODULES} ${PXE_MODULES} ${CRYPTO_MODULES} mdraid09 mdraid1x lvm serial" %ifarch ppc ppc64 ppc64le -GRUB_MODULES="${GRUB_MODULES} appendedsig memdisk tar regexp" +GRUB_MODULES="${GRUB_MODULES} appendedsig memdisk tar regexp prep_loadenv" %endif %ifarch %{efi} @@ -675,7 +678,6 @@ %endif %ifarch x86_64 aarch64 -%if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110 if test -e %{_sourcedir}/_projectcert.crt ; then prjsubject=$(openssl x509 -in %{_sourcedir}/_projectcert.crt -noout -subject_hash) prjissuer=$(openssl x509 -in %{_sourcedir}/_projectcert.crt -noout -issuer_hash) @@ -698,7 +700,6 @@ openssl x509 -in $cert -outform DER -out grub.der %endif -%endif cd .. %endif @@ -729,8 +730,11 @@ make %{?_smp_mflags} if [ "%{platform}" = "ieee1275" ]; then - cert="%{_sourcedir}/_projectcert.crt" - openssl x509 -in "$cert" -outform DER -out grub.der + # So far neither OpenFirmware nor grub support CA chain, only certificate pinning + # Use project certificate always in the shipped informational file and + # for kernel verification + projectcert="%{_sourcedir}/_projectcert.crt" + openssl x509 -in "$projectcert" -outform DER -out grub.der cat > %{platform}-config <<'EOF' set root=memdisk set prefix=($root)/ @@ -744,39 +748,76 @@ echo "bpart=$bpart" echo "bpath=$bpath" +if [ "$btrfs_relative_path" = xy ]; then + btrfs_relative_path=1 +fi + if [ "$bdev" -a "$bpart" -a "$bpath" ]; then - hints="--hint $bdev$bpart" - cfg_dir="$bpath" + set hints="--hint $bdev$bpart" + set cfg_dir="$bpath" elif [ "$bdev" -a "$bpart" ]; then - hints="--hint $bdev$bpart" - cfg_dir="/boot/grub2 /grub2" + set hints="--hint $bdev$bpart" + set cfg_dir="/boot/grub2 /grub2" + set btrfs_relative_path=1 elif [ "$bdev" ]; then - hints="--hint ${bdev}," - cfg_dir="/boot/grub2 /grub2" + if [ "$ENV_HINT" ]; then + set hints="--hint $ENV_HINT" + else + set hints="--hint ${bdev}," + fi + if [ "$ENV_GRUB_DIR" ]; then + set cfg_dir="$ENV_GRUB_DIR" + else + set cfg_dir="/boot/grub2 /grub2" + set btrfs_relative_path=1 + fi else - hints="" - cfg_dir="/boot/grub2 /grub2" + set hints="" + set cfg_dir="/boot/grub2 /grub2" + set btrfs_relative_path=1 fi set prefix="" set root="" set cfg="grub.cfg" + +if [ "$ENV_CRYPTO_UUID" ]; then + cryptomount -u "$ENV_CRYPTO_UUID" +fi + +if [ "$ENV_FS_UUID" ]; then + echo "searching for $ENV_FS_UUID with $hints" + if search --fs-uuid --set=root "$ENV_FS_UUID" $hints; then + echo "$ENV_FS_UUID is on $root" + fi +fi + for d in ${cfg_dir}; do - set btrfs_relative_path=1 - echo "start searching for $d/${cfg} with $hints" + if [ -z "$root" ]; then + echo "searching for ${d}/${cfg}" if search --file --set=root "${d}/${cfg}" $hints; then echo "${d}/${cfg} is on $root" - set btrfs_relative_path=0 + prefix="($root)${d}" + fi + elif [ -f "${d}/${cfg}" ]; then + echo "${d}/${cfg} is on $root" + prefix="($root)${d}" + else + echo "${d}/${cfg} not found in $root" + fi + + if [ "$prefix" -a x"$btrfs_relative_path" = x1 ]; then + btrfs_relative_path=0 if [ -f /@"${d}"/powerpc-ieee1275/command.lst ]; then - set btrfs_relative_path=1 + btrfs_relative_path=1 echo "mounting subvolume @${d}/powerpc-ieee1275 on ${d}/powerpc-ieee1275" btrfs-mount-subvol ($root) "${d}"/powerpc-ieee1275 @"${d}"/powerpc-ieee1275 fi - set btrfs_relative_path=1 - set prefix="($root)${d}" + btrfs_relative_path=1 break fi done + echo "prefix=$prefix root=$root" if [ -n "$prefix" ]; then source "${prefix}/${cfg}" @@ -835,14 +876,12 @@ %endif %ifarch x86_64 aarch64 -%if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110 export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi" %ifarch x86_64 BRP_PESIGN_FILES="${BRP_PESIGN_FILES} %{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi" %endif install -m 444 grub.der %{buildroot}/%{sysefidir}/ %endif -%endif cd .. %endif @@ -1285,10 +1324,8 @@ %endif %ifarch x86_64 aarch64 -%if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110 %{sysefidir}/grub.der %endif -%endif %files %{grubefiarch}-debug %defattr(-,root,root,-) ++++++ 0001-Add-grub_envblk_buf-helper-function.patch ++++++ >From a326e486bdcf99e6be973ba54c0abfb6d2d95b73 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Mon, 17 Jan 2022 17:45:00 +0800 Subject: [PATCH 1/5] Add grub_envblk_buf helper function This helps in creation and initialization of memory buffer for environment block of given size. Signed-off-by: Michael Chang <mch...@suse.com> --- grub-core/lib/envblk.c | 12 ++++++++++++ include/grub/lib/envblk.h | 1 + util/grub-editenv.c | 4 +--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c index 2e4e78b132..24efbe7ffa 100644 --- a/grub-core/lib/envblk.c +++ b/grub-core/lib/envblk.c @@ -23,6 +23,18 @@ #include <grub/mm.h> #include <grub/lib/envblk.h> +char * +grub_envblk_buf (grub_size_t size) +{ + char *buf; + + buf = grub_malloc (size); + grub_memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); + grub_memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); + + return buf; +} + grub_envblk_t grub_envblk_open (char *buf, grub_size_t size) { diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h index c3e6559217..83f3fcf841 100644 --- a/include/grub/lib/envblk.h +++ b/include/grub/lib/envblk.h @@ -31,6 +31,7 @@ struct grub_envblk }; typedef struct grub_envblk *grub_envblk_t; +char *grub_envblk_buf (grub_size_t size); grub_envblk_t grub_envblk_open (char *buf, grub_size_t size); int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value); void grub_envblk_delete (grub_envblk_t envblk, const char *name); diff --git a/util/grub-editenv.c b/util/grub-editenv.c index b8219335f7..a02d3f2a63 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -210,9 +210,7 @@ create_envblk_fs (void) if (! fp) grub_util_error (_("cannot open `%s': %s"), device, strerror (errno)); - buf = xmalloc (size); - memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); - memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', size - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); + buf = grub_envblk_buf (size); if (fseek (fp, offset, SEEK_SET) < 0) grub_util_error (_("cannot seek `%s': %s"), device, strerror (errno)); -- 2.34.1 ++++++ 0002-Add-grub_disk_write_tail-helper-function.patch ++++++ >From c0d00403a297d6023eab6189ba87dc8a3f6d1e85 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Mon, 7 Feb 2022 20:44:40 +0800 Subject: [PATCH 2/5] Add grub_disk_write_tail helper function This helps in writing data to partition where the end of buffer is aligned to end of partition. Signed-off-by: Michael Chang <mch...@suse.com> --- grub-core/lib/disk.c | 18 ++++++++++++++++++ include/grub/disk.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c index b4eb064a81..08e24485f0 100644 --- a/grub-core/lib/disk.c +++ b/grub-core/lib/disk.c @@ -51,6 +51,24 @@ grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, } } +grub_err_t +grub_disk_write_tail (grub_disk_t disk, grub_size_t size, const void *buf) +{ + grub_partition_t part; + grub_disk_addr_t sector; + grub_off_t offset; + + if (!disk->partition) + return GRUB_ERR_NONE; + + part = disk->partition; + sector = part->len; + sector -= (size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS; + offset = size & (GRUB_DISK_SECTOR_SIZE - 1); + + return grub_disk_write (disk, sector, offset, size, buf); +} + grub_err_t grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, const void *buf) diff --git a/include/grub/disk.h b/include/grub/disk.h index f95aca929a..6d656c4315 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -232,6 +232,9 @@ grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk, grub_off_t offset, grub_size_t size, void *buf); +grub_err_t grub_disk_write_tail (grub_disk_t disk, + grub_size_t size, + const void *buf); grub_err_t grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, -- 2.34.1 ++++++ 0003-grub-install-support-prep-environment-block.patch ++++++ >From c31fc5aa0ded9ce1e774d0a3526cfee19be1b77f Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Mon, 7 Feb 2022 20:49:01 +0800 Subject: [PATCH 3/5] grub-install: support prep environment block The grub-install can be instructed to create environment block at end of PReP paritition with probed device identities and properties in variables to facilitate root device discovery. So far these variables are defined for this purpose: ENV_FS_UUID - The filesystem uuid for the grub root device ENV_CRYPTO_UUID - The crytodisk uuid for the grub root device ENV_GRUB_DIR - The path to grub prefix directory ENV_HINT - The recommended hint string for searching root device The size of environment block is defined in GRUB_ENVBLK_PREP_SIZE which is 4096 bytes and can be extended in the future. Signed-off-by: Michael Chang <mch...@suse.com> --- include/grub/lib/envblk.h | 3 +++ util/grub-install.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h index 83f3fcf841..d01927bcf7 100644 --- a/include/grub/lib/envblk.h +++ b/include/grub/lib/envblk.h @@ -24,6 +24,9 @@ #ifndef ASM_FILE +#include <grub/disk.h> +#define GRUB_ENVBLK_PREP_SIZE (GRUB_DISK_SECTOR_SIZE << 3) + struct grub_envblk { char *buf; diff --git a/util/grub-install.c b/util/grub-install.c index 8fb5ea616b..7bc5f84378 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -43,6 +43,7 @@ #include <grub/util/ofpath.h> #include <grub/hfsplus.h> #include <grub/time.h> +#include <grub/lib/envblk.h> #include <string.h> @@ -2112,6 +2113,43 @@ main (int argc, char *argv[]) { grub_util_error ("%s", _("failed to copy Grub to the PReP partition")); } + + if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0))) + { + char *uuid = NULL; + const char *cryptouuid = NULL; + grub_envblk_t envblk = NULL; + char *buf; + + /* TODO: Add LVM/RAID on encrypted partitions */ + if (grub_dev->disk && grub_dev->disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + cryptouuid = grub_util_cryptodisk_get_uuid (grub_dev->disk); + if (grub_fs->fs_uuid && grub_fs->fs_uuid (grub_dev, &uuid)) + { + grub_print_error (); + grub_errno = 0; + uuid = NULL; + } + buf = grub_envblk_buf (GRUB_ENVBLK_PREP_SIZE); + envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE); + if (uuid) + grub_envblk_set (envblk, "ENV_FS_UUID", uuid); + if (cryptouuid) + grub_envblk_set (envblk, "ENV_CRYPTO_UUID", cryptouuid); + if (relative_grubdir) + grub_envblk_set (envblk, "ENV_GRUB_DIR", relative_grubdir); + if (have_abstractions) + grub_envblk_set (envblk, "ENV_HINT", grub_dev->disk->name); + if (use_relative_path_on_btrfs) + grub_envblk_set (envblk, "btrfs_relative_path", "1"); + if (envblk) + { + fprintf (stderr, _("Write environment block to PReP.\n")); + if (grub_disk_write_tail (ins_dev->disk, envblk->size, envblk->buf)) + grub_util_error ("%s", _("failed to write environment block to the PReP partition")); + } + grub_envblk_close (envblk); + } grub_device_close (ins_dev); if (update_nvram) grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device), -- 2.34.1 ++++++ 0004-Introduce-prep_load_env-command.patch ++++++ >From 3cf4fdf8d17423dea4e5913ab14fb6305f3c2571 Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Fri, 18 Feb 2022 21:43:38 +0800 Subject: [PATCH 4/5] Introduce prep_load_env command This command will accept grub disk device and perform load_env for environment block located at end of PReP partition which belongs to that input disk device. All variables read from that environment block are exported to grub as environment variables. Please note there's no support for whitelist variables and also --skip-sig option compared to ordinary load_env command. Signed-off-by: Michael Chang <mch...@suse.com> --- grub-core/Makefile.core.def | 5 + grub-core/commands/prep_loadenv.c | 227 ++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 grub-core/commands/prep_loadenv.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 49bdb63b69..4d529859be 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -2624,3 +2624,8 @@ module = { common = lib/libtasn1_wrap/tests/Test_strings.c; common = lib/libtasn1_wrap/wrap_tests.c; }; + +module = { + name = prep_loadenv; + common = commands/prep_loadenv.c; +}; diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c new file mode 100644 index 0000000000..f4bb270a2b --- /dev/null +++ b/grub-core/commands/prep_loadenv.c @@ -0,0 +1,227 @@ +#include <grub/dl.h> +#include <grub/mm.h> +#include <grub/file.h> +#include <grub/disk.h> +#include <grub/misc.h> +#include <grub/err.h> +#include <grub/env.h> +#include <grub/partition.h> +#include <grub/lib/envblk.h> +#include <grub/extcmd.h> +#include <grub/i18n.h> +#include <grub/gpt_partition.h> + +GRUB_MOD_LICENSE ("GPLv3+"); + +static char * +match_substr (regmatch_t *match, const char *str) +{ + if (match->rm_so != -1) + { + char *substr; + regoff_t sz = match->rm_eo - match->rm_so; + + if (!sz) + return NULL; + substr = grub_malloc (1 + sz); + if (!substr) + { + grub_print_error (); + return NULL; + } + grub_memcpy (substr, str + match->rm_so, sz); + substr[sz] = '\0'; + return substr; + } + + return NULL; +} + +static int +is_prep_partition (grub_device_t dev) +{ + if (!dev->disk) + return 0; + if (!dev->disk->partition) + return 0; + if (grub_strcmp (dev->disk->partition->partmap->name, "msdos") == 0) + return (dev->disk->partition->msdostype == 0x41); + + if (grub_strcmp (dev->disk->partition->partmap->name, "gpt") == 0) + { + struct grub_gpt_partentry gptdata; + grub_partition_t p = dev->disk->partition; + int ret = 0; + dev->disk->partition = dev->disk->partition->parent; + + if (grub_disk_read (dev->disk, p->offset, p->index, + sizeof (gptdata), &gptdata) == 0) + { + const grub_gpt_part_guid_t template = { + grub_cpu_to_le32_compile_time (0x9e1a2d38), + grub_cpu_to_le16_compile_time (0xc612), + grub_cpu_to_le16_compile_time (0x4316), + { 0xaa, 0x26, 0x8b, 0x49, 0x52, 0x1e, 0x5a, 0x8b } + }; + + ret = grub_memcmp (&template, &gptdata.type, + sizeof (template)) == 0; + } + dev->disk->partition = p; + return ret; + } + + return 0; +} + +static int +part_hook (grub_disk_t disk, const grub_partition_t partition, void *data) +{ + char **ret = data; + char *partition_name, *devname; + grub_device_t dev; + + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 2; + + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 2; + + dev = grub_device_open (devname); + if (!dev) + { + grub_free (devname); + return 2; + } + if (is_prep_partition (dev)) + { + *ret = devname; + return 1; + } + grub_free (devname); + grub_device_close (dev); + return 0; +} + +static int +set_var (const char *name, const char *value, + void *hook_data __attribute__ ((unused))) +{ + grub_env_set (name, value); + grub_env_export (name); + return 0; +} + +static grub_err_t +prep_read_envblk (const char *devname) +{ + char *buf = NULL; + grub_device_t dev = NULL; + grub_envblk_t envblk = NULL; + + dev = grub_device_open (devname); + if (!dev) + return grub_errno; + + if (!dev->disk || !dev->disk->partition) + { + grub_error (GRUB_ERR_BAD_DEVICE, "disk device required"); + goto fail; + } + + buf = grub_malloc (GRUB_ENVBLK_PREP_SIZE); + if (!buf) + goto fail; + + if (grub_disk_read (dev->disk, dev->disk->partition->len - (GRUB_ENVBLK_PREP_SIZE >> GRUB_DISK_SECTOR_BITS), 0, GRUB_ENVBLK_PREP_SIZE, buf)) + goto fail; + + envblk = grub_envblk_open (buf, GRUB_ENVBLK_PREP_SIZE); + if (!envblk) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block"); + goto fail; + } + grub_envblk_iterate (envblk, NULL, set_var); + + fail: + if (envblk) + grub_envblk_close (envblk); + else + grub_free (buf); + if (dev) + grub_device_close (dev); + return grub_errno; +} + +static grub_err_t +prep_partname (const char *devname, char **prep) +{ + grub_device_t dev = NULL; + grub_err_t err; + int ret; + + dev = grub_device_open (devname); + if (!dev) + return grub_errno; + + ret = grub_partition_iterate (dev->disk, part_hook, prep); + if (ret == 1 && *prep) + { + err = GRUB_ERR_NONE; + goto out; + } + else if (ret == 0 && grub_errno == GRUB_ERR_NONE) + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "no prep partition"); + else + err = grub_errno; + + out: + grub_device_close (dev); + return err; +} + +static grub_err_t +grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), + int argc, + char **argv) +{ + char *devname, *prep = NULL; + grub_err_t err; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + + devname = grub_file_get_device_name(argv[0]); + if (!devname) + return grub_errno; + + err = prep_partname (devname, &prep); + if (prep == NULL || err != GRUB_ERR_NONE) + goto out; + + err = prep_read_envblk (prep); + + out: + grub_free (devname); + grub_free (prep); + return err; +} + +static grub_command_t cmd_prep_load; + +GRUB_MOD_INIT(prep_loadenv) +{ + cmd_prep_load = + grub_register_command("prep_load_env", grub_cmd_prep_loadenv, + "DEVICE", + N_("Load variables from environment block file.")); +} + +GRUB_MOD_FINI(prep_loadenv) +{ + grub_unregister_command (cmd_prep_load); +} -- 2.34.1 ++++++ 0005-export-environment-at-start-up.patch ++++++ >From 496b6b20cbce3fc27228d1d8290089fb7107b8de Mon Sep 17 00:00:00 2001 From: Michael Chang <mch...@suse.com> Date: Fri, 18 Feb 2022 21:51:16 +0800 Subject: [PATCH 5/5] export environment at start up If the prep_loadenv module is built into the core image, it will read the environment block automatically during start up and export all variables. The will ease integration with those without early scripts to running the command. Signed-off-by: Michael Chang <mch...@suse.com> --- grub-core/Makefile.core.def | 2 + grub-core/commands/prep_loadenv.c | 77 +++++++++++++++++++++++++++++++ grub-core/kern/env.c | 2 + grub-core/kern/main.c | 3 ++ include/grub/env.h | 1 + 5 files changed, 85 insertions(+) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 4d529859be..f3140815b8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -2628,4 +2628,6 @@ module = { module = { name = prep_loadenv; common = commands/prep_loadenv.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; diff --git a/grub-core/commands/prep_loadenv.c b/grub-core/commands/prep_loadenv.c index f4bb270a2b..4f40f7e41a 100644 --- a/grub-core/commands/prep_loadenv.c +++ b/grub-core/commands/prep_loadenv.c @@ -10,6 +10,7 @@ #include <grub/extcmd.h> #include <grub/i18n.h> #include <grub/gpt_partition.h> +#include <regex.h> GRUB_MOD_LICENSE ("GPLv3+"); @@ -184,6 +185,65 @@ prep_partname (const char *devname, char **prep) return err; } +static grub_err_t +boot_disk_prep_partname (char **name) +{ + regex_t regex; + int ret; + grub_size_t s; + char *comperr; + const char *cmdpath; + regmatch_t *matches = NULL; + grub_err_t err = GRUB_ERR_NONE; + + *name = NULL; + + cmdpath = grub_env_get ("cmdpath"); + if (!cmdpath) + return GRUB_ERR_NONE; + + ret = regcomp (®ex, "\\(([^,]+)(,?.*)?\\)(.*)", REG_EXTENDED); + if (ret) + goto fail; + + matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches)); + if (! matches) + goto fail; + + ret = regexec (®ex, cmdpath, regex.re_nsub + 1, matches, 0); + if (!ret) + { + char *devname = devname = match_substr (matches + 1, cmdpath); + if (!devname) + { + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "%s contains no disk name", cmdpath); + goto out; + } + + err = prep_partname (devname, name); + out: + grub_free (devname); + regfree (®ex); + grub_free (matches); + return err; + } + + fail: + grub_free (matches); + s = regerror (ret, ®ex, 0, 0); + comperr = grub_malloc (s); + if (!comperr) + { + regfree (®ex); + return grub_errno; + } + regerror (ret, ®ex, comperr, s); + err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr); + regfree (®ex); + grub_free (comperr); + return err; +} + static grub_err_t grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), int argc, @@ -211,10 +271,27 @@ grub_cmd_prep_loadenv (grub_command_t cmd __attribute__ ((unused)), return err; } +static void +early_prep_loadenv (void) +{ + grub_err_t err; + char *prep; + + err = boot_disk_prep_partname (&prep); + if (err == GRUB_ERR_NONE && prep) + err = prep_read_envblk (prep); + if (err == GRUB_ERR_BAD_FILE_TYPE || err == GRUB_ERR_FILE_NOT_FOUND) + grub_error_pop (); + if (err != GRUB_ERR_NONE) + grub_print_error (); + grub_free (prep); +} + static grub_command_t cmd_prep_load; GRUB_MOD_INIT(prep_loadenv) { + early_env_hook = early_prep_loadenv; cmd_prep_load = grub_register_command("prep_load_env", grub_cmd_prep_loadenv, "DEVICE", diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c index c408626423..ec0d268905 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c @@ -28,6 +28,8 @@ static struct grub_env_context initial_context; /* The current context. */ struct grub_env_context *grub_current_context = &initial_context; +void (*early_env_hook) (void) = NULL; + /* Return the hash representation of the string S. */ static unsigned int grub_env_hashval (const char *s) diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index c7c6d2d0b8..42ea96e39e 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -310,6 +310,9 @@ grub_main (void) grub_boot_time ("Before execution of embedded config."); + if (early_env_hook != NULL) + early_env_hook (); + if (load_config) grub_parser_execute (load_config); diff --git a/include/grub/env.h b/include/grub/env.h index 76f832eb94..636e190a21 100644 --- a/include/grub/env.h +++ b/include/grub/env.h @@ -68,5 +68,6 @@ grub_env_extractor_open (int source); grub_err_t grub_env_extractor_close (int source); +extern void (*EXPORT_VAR (early_env_hook)) (void); #endif /* ! GRUB_ENV_HEADER */ -- 2.34.1