Merge pull request #2001 from agners/multi-device-tree
deploy: support devicetree directory
This commit is contained in:
commit
adcd261596
|
|
@ -144,6 +144,10 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
|
||||||
if (val)
|
if (val)
|
||||||
g_ptr_array_add (new_lines, g_strdup_printf ("fdt_file%s=%s", index_suffix, val));
|
g_ptr_array_add (new_lines, g_strdup_printf ("fdt_file%s=%s", index_suffix, val));
|
||||||
|
|
||||||
|
val = ostree_bootconfig_parser_get (config, "fdtdir");
|
||||||
|
if (val)
|
||||||
|
g_ptr_array_add (new_lines, g_strdup_printf ("fdtdir%s=%s", index_suffix, val));
|
||||||
|
|
||||||
val = ostree_bootconfig_parser_get (config, "options");
|
val = ostree_bootconfig_parser_get (config, "options");
|
||||||
if (val)
|
if (val)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,79 @@ dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
str_sort_cb (gconstpointer name_ptr_a, gconstpointer name_ptr_b)
|
||||||
|
{
|
||||||
|
const gchar *name_a = *((const gchar **) name_ptr_a);
|
||||||
|
const gchar *name_b = *((const gchar **) name_ptr_b);
|
||||||
|
|
||||||
|
return g_strcmp0 (name_a, name_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
checksum_dir_recurse (int dfd,
|
||||||
|
const char *path,
|
||||||
|
OtChecksum *checksum,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_auto(GLnxDirFdIterator) dfditer = { 0, };
|
||||||
|
g_autoptr (GPtrArray) d_entries = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
|
||||||
|
if (!glnx_dirfd_iterator_init_at (dfd, path, TRUE, &dfditer, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
struct dirent *dent;
|
||||||
|
|
||||||
|
if (!glnx_dirfd_iterator_next_dent (&dfditer, &dent, cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (dent == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
g_ptr_array_add (d_entries, g_strdup (dent->d_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File systems do not guarantee dir entry order, make sure this is
|
||||||
|
* reproducable
|
||||||
|
*/
|
||||||
|
g_ptr_array_sort(d_entries, str_sort_cb);
|
||||||
|
|
||||||
|
for (gint i=0; i < d_entries->len; i++)
|
||||||
|
{
|
||||||
|
const gchar *d_name = (gchar *)g_ptr_array_index (d_entries, i);
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
if (!glnx_fstatat (dfditer.fd, d_name, &stbuf,
|
||||||
|
AT_SYMLINK_NOFOLLOW, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (S_ISDIR (stbuf.st_mode))
|
||||||
|
{
|
||||||
|
if (!checksum_dir_recurse(dfditer.fd, d_name, checksum, cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (!ot_openat_ignore_enoent (dfditer.fd, d_name, &fd, error))
|
||||||
|
return FALSE;
|
||||||
|
if (fd != -1)
|
||||||
|
{
|
||||||
|
g_autoptr(GInputStream) in = g_unix_input_stream_new (fd, FALSE);
|
||||||
|
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
copy_dir_recurse (int src_parent_dfd,
|
copy_dir_recurse (int src_parent_dfd,
|
||||||
int dest_parent_dfd,
|
int dest_parent_dfd,
|
||||||
|
|
@ -1065,6 +1138,9 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
|
||||||
g_clear_object (&in);
|
g_clear_object (&in);
|
||||||
glnx_close_fd (&fd);
|
glnx_close_fd (&fd);
|
||||||
|
|
||||||
|
/* Check for /usr/lib/modules/$kver/devicetree first, if it does not
|
||||||
|
* exist check for /usr/lib/modules/$kver/dtb/ directory.
|
||||||
|
*/
|
||||||
if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error))
|
if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
|
|
@ -1075,6 +1151,23 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
|
||||||
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
|
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
/* Check for dtb directory */
|
||||||
|
if (!glnx_fstatat_allow_noent (ret_layout->boot_dfd, "dtb", &stbuf, 0, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (errno == 0 && S_ISDIR (stbuf.st_mode))
|
||||||
|
{
|
||||||
|
/* devicetree_namever set to NULL indicates a complete directory */
|
||||||
|
ret_layout->devicetree_srcpath = g_strdup ("dtb");
|
||||||
|
ret_layout->devicetree_namever = NULL;
|
||||||
|
|
||||||
|
if (!checksum_dir_recurse(ret_layout->boot_dfd, "dtb", &checksum, cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_clear_object (&in);
|
g_clear_object (&in);
|
||||||
glnx_close_fd (&fd);
|
glnx_close_fd (&fd);
|
||||||
|
|
@ -1730,15 +1823,24 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
||||||
|
|
||||||
if (kernel_layout->devicetree_srcpath)
|
if (kernel_layout->devicetree_srcpath)
|
||||||
{
|
{
|
||||||
g_assert (kernel_layout->devicetree_namever);
|
/* If devicetree_namever is set a single device tree is deployed */
|
||||||
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
|
if (kernel_layout->devicetree_namever)
|
||||||
return FALSE;
|
|
||||||
if (errno == ENOENT)
|
|
||||||
{
|
{
|
||||||
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath,
|
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
|
||||||
bootcsum_dfd, kernel_layout->devicetree_namever,
|
return FALSE;
|
||||||
sysroot->debug_flags,
|
if (errno == ENOENT)
|
||||||
cancellable, error))
|
{
|
||||||
|
if (!install_into_boot (repo, sepolicy, kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath,
|
||||||
|
bootcsum_dfd, kernel_layout->devicetree_namever,
|
||||||
|
sysroot->debug_flags,
|
||||||
|
cancellable, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!copy_dir_recurse(kernel_layout->boot_dfd, bootcsum_dfd, kernel_layout->devicetree_srcpath,
|
||||||
|
sysroot->debug_flags, cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1850,6 +1952,15 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
||||||
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
|
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
|
||||||
ostree_bootconfig_parser_set (bootconfig, "devicetree", boot_relpath);
|
ostree_bootconfig_parser_set (bootconfig, "devicetree", boot_relpath);
|
||||||
}
|
}
|
||||||
|
else if (kernel_layout->devicetree_srcpath)
|
||||||
|
{
|
||||||
|
/* If devicetree_srcpath is set but devicetree_namever is NULL, then we
|
||||||
|
* want to point to a whole directory of device trees.
|
||||||
|
* See: https://github.com/ostreedev/ostree/issues/1900
|
||||||
|
*/
|
||||||
|
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_srcpath, NULL);
|
||||||
|
ostree_bootconfig_parser_set (bootconfig, "fdtdir", boot_relpath);
|
||||||
|
}
|
||||||
|
|
||||||
/* Note this is parsed in ostree-impl-system-generator.c */
|
/* Note this is parsed in ostree-impl-system-generator.c */
|
||||||
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",
|
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,11 @@ set -euo pipefail
|
||||||
. $(dirname $0)/libtest.sh
|
. $(dirname $0)/libtest.sh
|
||||||
|
|
||||||
# Exports OSTREE_SYSROOT so --sysroot not needed.
|
# Exports OSTREE_SYSROOT so --sysroot not needed.
|
||||||
setup_os_repository "archive" "uboot"
|
kver="3.6.0"
|
||||||
|
modulesdir="usr/lib/modules/${kver}"
|
||||||
|
setup_os_repository "archive" "uboot" ${modulesdir}
|
||||||
|
|
||||||
extra_admin_tests=1
|
extra_admin_tests=2
|
||||||
|
|
||||||
. $(dirname $0)/admin-test.sh
|
. $(dirname $0)/admin-test.sh
|
||||||
|
|
||||||
|
|
@ -52,3 +54,27 @@ assert_file_has_content sysroot/boot/uEnv.txt "kernel_image2="
|
||||||
assert_file_has_content sysroot/boot/uEnv.txt "kernel_image3="
|
assert_file_has_content sysroot/boot/uEnv.txt "kernel_image3="
|
||||||
|
|
||||||
echo "ok merging uEnv.txt files"
|
echo "ok merging uEnv.txt files"
|
||||||
|
|
||||||
|
cd ${test_tmpdir}
|
||||||
|
os_repository_new_commit "uboot test" "test with device tree directory"
|
||||||
|
|
||||||
|
devicetree_path=osdata/${modulesdir}/dtb/asoc-board.dtb
|
||||||
|
devicetree_overlay_path=osdata/${modulesdir}/dtb/overlays/overlay.dtbo
|
||||||
|
|
||||||
|
mkdir -p osdata/${modulesdir}/dtb
|
||||||
|
echo "a device tree" > ${devicetree_path}
|
||||||
|
mkdir -p osdata/${modulesdir}/dtb/overlays
|
||||||
|
echo "a device tree overlay" > ${devicetree_overlay_path}
|
||||||
|
|
||||||
|
bootcsum=$(
|
||||||
|
(echo "new: a kernel uboot test" && echo "new: an initramfs uboot test" &&
|
||||||
|
cat ${devicetree_path} ${devicetree_overlay_path} ) |
|
||||||
|
sha256sum | cut -f 1 -d ' ')
|
||||||
|
|
||||||
|
${CMD_PREFIX} ostree --repo=testos-repo commit --tree=dir=osdata/ -b testos/buildmaster/x86_64-runtime
|
||||||
|
${CMD_PREFIX} ostree admin upgrade --os=testos
|
||||||
|
assert_file_has_content sysroot/boot/uEnv.txt "fdtdir="
|
||||||
|
assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/dtb/asoc-board.dtb 'a device tree'
|
||||||
|
assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/dtb/overlays/overlay.dtbo 'a device tree overlay'
|
||||||
|
|
||||||
|
echo "ok deploying fdtdir"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue