Skip to content

Commit

Permalink
feat: use a custom grub message if GRUB_OSTREE_CUSTOM_DESC is set in …
Browse files Browse the repository at this point in the history
…grub
  • Loading branch information
zhaohuiw42 committed Oct 12, 2024
1 parent 4becf6b commit 900320b
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 0 deletions.
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
ostree (2024.6-1deepin3) unstable; urgency=medium

* use a custom grub message if GRUB_OSTREE_CUSTOM_DESC is set in grub

-- wangzhaohui <[email protected]> Sat, 12 Oct 2024 15:21:52 +0800

ostree (2024.6-1deepin2) unstable; urgency=medium

* curl: Make socket callback during cleanup into no-op.
Expand Down
159 changes: 159 additions & 0 deletions debian/patches/deepin-use-custom-grub-message.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
Index: ostree/src/boot/grub2/grub2-15_ostree
===================================================================
--- ostree.orig/src/boot/grub2/grub2-15_ostree
+++ ostree/src/boot/grub2/grub2-15_ostree
@@ -62,4 +62,8 @@ export GRUB2_BOOT_DEVICE_ID
GRUB2_PREPARE_ROOT_CACHE="$(prepare_grub_to_access_device ${DEVICE})"
export GRUB2_PREPARE_ROOT_CACHE

+if [ "x${GRUB_OSTREE_CUSTOM_DESC}" = "xtrue" ] ; then
+ export GRUB_OSTREE_CUSTOM_DESC=true
+fi
+
exec ostree admin instutil grub2-generate
Index: ostree/src/libostree/ostree-bootloader-grub2.c
===================================================================
--- ostree.orig/src/libostree/ostree-bootloader-grub2.c
+++ ostree/src/libostree/ostree-bootloader-grub2.c
@@ -25,6 +25,8 @@
#include <sys/mount.h>

#include <string.h>
+#include <locale.h>
+#include <libintl.h>

// Written by bootupd
#define BOOTUPD_CONFIG "boot/bootupd-state.json"
@@ -166,6 +168,78 @@ _ostree_bootloader_grub2_get_name (Ostre
return "grub2";
}

+static char *
+ostree_deployment_get_time(OstreeSysroot *sysroot, OstreeDeployment *deployment)
+{
+ if (sysroot == NULL || deployment == NULL)
+ return NULL;
+
+ g_autofree char *deploy_path =
+ g_file_get_path(ostree_sysroot_get_deployment_directory(sysroot, deployment));
+
+ struct stat target_info;
+ if (stat(deploy_path, &target_info) != 0)
+ return NULL;
+
+ char deploy_time[20];
+ struct tm *tm_info;
+
+ tm_info = localtime(&target_info.st_mtime);
+ strftime(deploy_time, sizeof(deploy_time), "%Y/%m/%d %H:%M:%S", tm_info);
+
+ return g_strdup(deploy_time);
+}
+
+static const char *
+ostree_update_grub_boot_message(OstreeSysroot *sysroot, gboolean grub_in_thread,
+ const char *title, guint index)
+{
+ g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments(sysroot);
+
+ if (index >= deployments->len)
+ return title;
+
+ g_autofree char *deploy_time = NULL;
+ /* When ostree has a staged deployment, a subprocess is spawned to call grub-mkconfig.
+ * However, the subprocess does not include the staged deployment in its deployment state,
+ * so we need to retrieve the deployment time from the OSTREE_STAGE_DEPLOY_TIME environment
+ * variable.
+ */
+ if (grub_in_thread)
+ {
+ if (index == 0)
+ {
+ const char *stage_deploy_time = g_getenv("OSTREE_STAGE_DEPLOY_TIME");
+ deploy_time = stage_deploy_time ? g_strdup_printf("%s", stage_deploy_time) : stage_deploy_time;
+ }
+ else
+ {
+ deploy_time = ostree_deployment_get_time(sysroot, deployments->pdata[index - 1]);
+ }
+ }
+ else
+ {
+ deploy_time = ostree_deployment_get_time(sysroot, deployments->pdata[index]);
+ }
+
+ if (deploy_time)
+ {
+ setlocale(LC_ALL, "");
+ bindtextdomain("ostree", "/usr/share/locale");
+ textdomain("ostree");
+
+ // remove substring " (ostree"
+ char *p = strstr(title, " (ostree");
+ if (p)
+ *p = '\0';
+
+ return index ? g_strdup_printf("%s %s (%s)", gettext("Roll back to"), title, deploy_time)
+ : g_strdup_printf("%s (%s)", title, deploy_time);
+ }
+
+ return title;
+}
+
/* This implementation is quite complex; see this issue for
* a starting point:
* https://github.com/ostreedev/ostree/issues/717
@@ -187,6 +261,8 @@ _ostree_bootloader_grub2_generate_config

/* Passed from the parent */
gboolean is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL;
+ gboolean grub_custom_desc = g_getenv ("GRUB_OSTREE_CUSTOM_DESC") != NULL;
+ gboolean grub_in_thread = g_getenv ("GRUB_MKCONFIG_IN_THREAD") != NULL;

g_autoptr (GOutputStream) out_stream = g_unix_output_stream_new (target_fd, FALSE);

@@ -214,6 +290,8 @@ _ostree_bootloader_grub2_generate_config

kernel = ostree_bootconfig_parser_get (config, "linux");

+ if (grub_custom_desc)
+ title = ostree_update_grub_boot_message(sysroot, grub_in_thread, title, i);
quoted_title = g_shell_quote (title);
uuid = g_strdup_printf ("ostree-%u-%s", (guint)i, grub2_boot_device_id);
quoted_uuid = g_shell_quote (uuid);
@@ -285,6 +363,8 @@ typedef struct
{
const char *root;
const char *bootversion_str;
+ /* Used for child grub2-mkconfig to get deploy time of staged one */
+ const char *stage_deploy_time;
gboolean is_efi;
} Grub2ChildSetupData;

@@ -294,11 +374,14 @@ grub2_child_setup (gpointer user_data)
{
Grub2ChildSetupData *cdata = user_data;

+ setenv ("GRUB_MKCONFIG_IN_THREAD", "true", TRUE);
setenv ("_OSTREE_GRUB2_BOOTVERSION", cdata->bootversion_str, TRUE);
/* We have to pass our state (whether or not we're using EFI) to the child */
if (cdata->is_efi)
setenv ("_OSTREE_GRUB2_IS_EFI", "1", TRUE);

+ if (cdata->stage_deploy_time)
+ setenv ("OSTREE_STAGE_DEPLOY_TIME", cdata->stage_deploy_time, TRUE);
/* Everything below this is dealing with the chroot case; if
* we're not doing that, return early.
*/
@@ -425,6 +508,11 @@ _ostree_bootloader_grub2_write_config (O
g_autofree char *bootversion_str = g_strdup_printf ("%u", (guint)bootversion);
cdata.bootversion_str = bootversion_str;
cdata.is_efi = self->is_efi;
+ /* The first deployment of new_deployments should be the staged one, pass its
+ deploy time to child grub-mkconfig to update grub boot message.
+ */
+ if (new_deployments->len)
+ cdata.stage_deploy_time = ostree_deployment_get_time (self->sysroot, new_deployments->pdata[0]);
/* Note in older versions of the grub2 package, this script doesn't even try
to be atomic; it just does:

1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ debian/test-sysroot-Skip-on-s390x-by-default.patch
debian/Skip-test-admin-deploy-uboot.sh-on-s390x.patch
deepin-deploy-when-root-is-overlay.patch
make-socket-callback-during-cleanup-into.patch
deepin-use-custom-grub-message.patch

0 comments on commit 900320b

Please sign in to comment.