summaryrefslogtreecommitdiffstats
path: root/recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch')
-rw-r--r--recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch130
1 files changed, 130 insertions, 0 deletions
diff --git a/recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch b/recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch
new file mode 100644
index 0000000..960367c
--- /dev/null
+++ b/recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch
@@ -0,0 +1,130 @@
1From 310ddd84dc353d93a2cc118725b459dba643cf0b Mon Sep 17 00:00:00 2001
2From: Gatis Paeglis <gatis.paeglis@theqtcompany.com>
3Date: Thu, 21 Apr 2016 16:54:05 +0200
4Subject: [PATCH 3/3] Create firmware convenience symlinks.
5
6Later this could be moved into utils or a similar
7location, if other boot loader backends will need
8this functionality.
9---
10 src/libostree/ostree-bootloader-uboot.c | 97 ++++++++++++++++++++++++++++++++-
11 1 file changed, 96 insertions(+), 1 deletion(-)
12
13diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c
14index 9bcde9c..be5e8c5 100644
15--- a/src/libostree/ostree-bootloader-uboot.c
16+++ b/src/libostree/ostree-bootloader-uboot.c
17@@ -66,6 +66,100 @@ _ostree_bootloader_uboot_get_name (OstreeBootloader *bootloader)
18 return "U-Boot";
19 }
20
21+/* It is common for firmware to search / on the boot partition for additional
22+ * files that are required for booting. It can be difficult to change this search
23+ * logic if it is hardcoded somewhere low in the stack or is in a read-only memory.
24+ * This issue can be solved from the OS installer, by creating a symlink in the
25+ * following way:
26+ *
27+ * cd sysroot/boot
28+ * ln -s loader/second-stage-bootloader second-stage-bootloader
29+ *
30+ * This function will make sure that loader/second-stage-bootloader points to the
31+ * correct target file version. This function does nothing if boot/ does not contain
32+ * symlink files pointing into loader/.
33+ */
34+static gboolean
35+create_firmware_convenience_symlinks (OstreeBootloaderUboot *self,
36+ char *bootcsum_dir,
37+ int bootversion,
38+ GCancellable *cancellable,
39+ GError **error)
40+{
41+ gboolean ret = FALSE;
42+ glnx_fd_close int loader_dfd = -1;
43+ glnx_fd_close int boot_dfd = -1;
44+ g_autofree char *loader_dir = NULL;
45+ g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
46+
47+ loader_dir = g_strdup_printf ("boot/loader.%d/", bootversion);
48+ if (!glnx_opendirat (self->sysroot->sysroot_fd, loader_dir, FALSE, &loader_dfd, error))
49+ goto out;
50+ if (!glnx_opendirat (self->sysroot->sysroot_fd, "boot", FALSE, &boot_dfd, error))
51+ goto out;
52+ if (!glnx_dirfd_iterator_init_take_fd (dup (boot_dfd), &dfd_iter, error))
53+ goto out;
54+
55+ while (TRUE) {
56+ struct dirent *dent;
57+ struct stat stbuf;
58+
59+ if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
60+ goto out;
61+ if (dent == NULL)
62+ break;
63+
64+ if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
65+ {
66+ if (errno == ENOENT)
67+ continue;
68+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "fstatat");
69+ goto out;
70+ }
71+
72+ if (S_ISLNK(stbuf.st_mode))
73+ {
74+ char path_buffer[PATH_MAX];
75+ g_autofree char *symlink_target = NULL;
76+ symlink_target = glnx_readlinkat_malloc (boot_dfd, dent->d_name, cancellable, error);
77+
78+ if (g_str_has_prefix (symlink_target, "loader/"))
79+ {
80+ if (g_strcmp0 (dent->d_name, "uEnv.txt") == 0)
81+ continue;
82+
83+ snprintf (path_buffer, sizeof(path_buffer), "%s/%s", bootcsum_dir, dent->d_name);
84+ if (faccessat (boot_dfd, path_buffer + 1, F_OK, AT_SYMLINK_NOFOLLOW) == -1)
85+ {
86+ /* This bootcsum dir does not contain the final target, do nothing. */
87+ if (errno == ENOENT)
88+ continue;
89+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "faccessat");
90+ goto out;
91+ }
92+
93+ /* In case 'ostree admin cleanup' was not run after an interrupted deployment */
94+ if (unlinkat (loader_dfd, dent->d_name, 0) == -1 && errno != ENOENT)
95+ {
96+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "unlinkat");
97+ goto out;
98+ }
99+ /* Complete the link chain to the current boot file version */
100+ snprintf (path_buffer, sizeof(path_buffer), "..%s/%s", bootcsum_dir, dent->d_name);
101+ if (symlinkat (path_buffer, loader_dfd, dent->d_name) == -1)
102+ {
103+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "symlinkat");
104+ goto out;
105+ }
106+ }
107+ }
108+ }
109+
110+ ret = TRUE;
111+out:
112+ return ret;
113+}
114+
115 static gboolean
116 create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
117 int bootversion,
118@@ -130,7 +224,8 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
119 }
120 }
121
122- ret = TRUE;
123+ ret = create_firmware_convenience_symlinks (self, bootdir, bootversion, cancellable, error);
124+
125 out:
126 return ret;
127 }
128--
1292.7.4
130