diff options
Diffstat (limited to 'meta-boot2qt/recipes-core/ostree/ostree/Create-firmware-convenience-symlinks.patch')
-rw-r--r-- | meta-boot2qt/recipes-core/ostree/ostree/Create-firmware-convenience-symlinks.patch | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/meta-boot2qt/recipes-core/ostree/ostree/Create-firmware-convenience-symlinks.patch b/meta-boot2qt/recipes-core/ostree/ostree/Create-firmware-convenience-symlinks.patch new file mode 100644 index 0000000..656887d --- /dev/null +++ b/meta-boot2qt/recipes-core/ostree/ostree/Create-firmware-convenience-symlinks.patch | |||
@@ -0,0 +1,126 @@ | |||
1 | From c4df63488b9e09a9aa69e32ea5c0671c9dc50c9d Mon Sep 17 00:00:00 2001 | ||
2 | From: Gatis Paeglis <gatis.paeglis@qt.io> | ||
3 | Date: Wed, 24 Aug 2016 12:29:38 +0200 | ||
4 | Subject: [PATCH] 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 | 93 ++++++++++++++++++++++++++++++++- | ||
11 | 1 file changed, 92 insertions(+), 1 deletion(-) | ||
12 | |||
13 | diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c | ||
14 | index 22251da..26a3127 100644 | ||
15 | --- a/src/libostree/ostree-bootloader-uboot.c | ||
16 | +++ b/src/libostree/ostree-bootloader-uboot.c | ||
17 | @@ -62,6 +62,97 @@ _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 by system builders by creating a convenience symlink: | ||
25 | + * | ||
26 | + * cd sysroot/boot | ||
27 | + * ln -s loader/second-stage-bootloader second-stage-bootloader | ||
28 | + * | ||
29 | + * This function will make sure that loader/second-stage-bootloader points to the | ||
30 | + * correct target file version. This function does nothing if boot/ does not contain | ||
31 | + * symlink files pointing into the loader/ directory. | ||
32 | + */ | ||
33 | +static gboolean | ||
34 | +create_firmware_convenience_symlinks (OstreeBootloaderUboot *self, | ||
35 | + char *bootcsum_dir, | ||
36 | + int bootversion, | ||
37 | + GCancellable *cancellable, | ||
38 | + GError **error) | ||
39 | +{ | ||
40 | + glnx_fd_close int loader_dfd = -1; | ||
41 | + glnx_fd_close int boot_dfd = -1; | ||
42 | + g_autofree char *loader_dir = NULL; | ||
43 | + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; | ||
44 | + | ||
45 | + loader_dir = g_strdup_printf ("boot/loader.%d/", bootversion); | ||
46 | + if (!glnx_opendirat (self->sysroot->sysroot_fd, loader_dir, FALSE, &loader_dfd, error)) | ||
47 | + return FALSE; | ||
48 | + if (!glnx_opendirat (self->sysroot->sysroot_fd, "boot", FALSE, &boot_dfd, error)) | ||
49 | + return FALSE; | ||
50 | + if (!glnx_dirfd_iterator_init_take_fd (dup (boot_dfd), &dfd_iter, error)) | ||
51 | + return FALSE; | ||
52 | + | ||
53 | + while (TRUE) { | ||
54 | + struct dirent *dent; | ||
55 | + struct stat stbuf; | ||
56 | + | ||
57 | + if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) | ||
58 | + return FALSE; | ||
59 | + if (dent == NULL) | ||
60 | + break; | ||
61 | + | ||
62 | + if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0) | ||
63 | + { | ||
64 | + if (errno == ENOENT) | ||
65 | + continue; | ||
66 | + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "fstatat"); | ||
67 | + return FALSE; | ||
68 | + } | ||
69 | + | ||
70 | + if (S_ISLNK(stbuf.st_mode)) | ||
71 | + { | ||
72 | + char path_buffer[PATH_MAX]; | ||
73 | + g_autofree char *symlink_target = NULL; | ||
74 | + symlink_target = glnx_readlinkat_malloc (boot_dfd, dent->d_name, cancellable, error); | ||
75 | + | ||
76 | + if (g_str_has_prefix (symlink_target, "loader/")) | ||
77 | + { | ||
78 | + if (g_strcmp0 (dent->d_name, "uEnv.txt") == 0) | ||
79 | + continue; | ||
80 | + | ||
81 | + snprintf (path_buffer, sizeof(path_buffer), "%s/%s", bootcsum_dir, dent->d_name); | ||
82 | + if (faccessat (boot_dfd, path_buffer + 1, F_OK, AT_SYMLINK_NOFOLLOW) == -1) | ||
83 | + { | ||
84 | + /* This bootcsum dir does not contain the final target, do nothing. */ | ||
85 | + if (errno == ENOENT) | ||
86 | + continue; | ||
87 | + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "faccessat"); | ||
88 | + return FALSE; | ||
89 | + } | ||
90 | + | ||
91 | + /* Cleanup from stray symlinks. This can happend when the previous deployment was | ||
92 | + interrupted and no cleanup routines were run before restaring the deployment. */ | ||
93 | + if (unlinkat (loader_dfd, dent->d_name, 0) == -1 && errno != ENOENT) | ||
94 | + { | ||
95 | + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "unlinkat"); | ||
96 | + return FALSE; | ||
97 | + } | ||
98 | + /* Complete the link chain to the current boot file version. */ | ||
99 | + snprintf (path_buffer, sizeof(path_buffer), "..%s/%s", bootcsum_dir, dent->d_name); | ||
100 | + if (symlinkat (path_buffer, loader_dfd, dent->d_name) == -1) | ||
101 | + { | ||
102 | + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "symlinkat"); | ||
103 | + return FALSE; | ||
104 | + } | ||
105 | + } | ||
106 | + } | ||
107 | + } | ||
108 | + | ||
109 | + return TRUE; | ||
110 | +} | ||
111 | + | ||
112 | static gboolean | ||
113 | create_config_from_boot_loader_entries (OstreeBootloaderUboot *self, | ||
114 | int bootversion, | ||
115 | @@ -138,7 +229,7 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self, | ||
116 | } | ||
117 | } | ||
118 | |||
119 | - return TRUE; | ||
120 | + return create_firmware_convenience_symlinks (self, bootdir, bootversion, cancellable, error); | ||
121 | } | ||
122 | |||
123 | static gboolean | ||
124 | -- | ||
125 | 2.7.4 | ||
126 | |||