diff options
Diffstat (limited to 'recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch')
-rw-r--r-- | recipes/ostree/ostree/Create-firmware-convenience-symlinks.patch | 130 |
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 @@ | |||
1 | From 310ddd84dc353d93a2cc118725b459dba643cf0b Mon Sep 17 00:00:00 2001 | ||
2 | From: Gatis Paeglis <gatis.paeglis@theqtcompany.com> | ||
3 | Date: Thu, 21 Apr 2016 16:54:05 +0200 | ||
4 | Subject: [PATCH 3/3] Create firmware convenience symlinks. | ||
5 | |||
6 | Later this could be moved into utils or a similar | ||
7 | location, if other boot loader backends will need | ||
8 | this functionality. | ||
9 | --- | ||
10 | src/libostree/ostree-bootloader-uboot.c | 97 ++++++++++++++++++++++++++++++++- | ||
11 | 1 file changed, 96 insertions(+), 1 deletion(-) | ||
12 | |||
13 | diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c | ||
14 | index 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 | -- | ||
129 | 2.7.4 | ||
130 | |||