Merge pull request #2001 from agners/multi-device-tree

deploy: support devicetree directory
This commit is contained in:
OpenShift Merge Robot 2020-06-24 03:02:18 -04:00 committed by GitHub
commit adcd261596
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 10 deletions

View File

@ -144,6 +144,10 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
if (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");
if (val)
{

View File

@ -217,6 +217,79 @@ dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
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
copy_dir_recurse (int src_parent_dfd,
int dest_parent_dfd,
@ -1065,6 +1138,9 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd,
g_clear_object (&in);
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))
return FALSE;
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))
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);
glnx_close_fd (&fd);
@ -1730,15 +1823,24 @@ install_deployment_kernel (OstreeSysroot *sysroot,
if (kernel_layout->devicetree_srcpath)
{
g_assert (kernel_layout->devicetree_namever);
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
/* If devicetree_namever is set a single device tree is deployed */
if (kernel_layout->devicetree_namever)
{
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))
if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->devicetree_namever, &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
{
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;
}
}
@ -1850,6 +1952,15 @@ install_deployment_kernel (OstreeSysroot *sysroot,
g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
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 */
g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d",

View File

@ -25,9 +25,11 @@ set -euo pipefail
. $(dirname $0)/libtest.sh
# 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
@ -52,3 +54,27 @@ assert_file_has_content sysroot/boot/uEnv.txt "kernel_image2="
assert_file_has_content sysroot/boot/uEnv.txt "kernel_image3="
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"