The checksum should be a SHA256 hash of the kernel contents; it must be
pre-computed before storing the kernel in the repository. Optionally,
the directory can also contain an initramfs, stored as
-`initramfs(-.*)?-$checksum`. If this exists, the checksum must include
-both the kernel and initramfs contents. OSTree will use this to
-determine which kernels are shared. The rationale for this is to avoid
-computing checksums on the client by default.
+`initramfs(-.*)?-$checksum` and/or a device tree, stored as
+`devicetree(-.*)?-$checksum`. If an initramfs or devicetree exist,
+the checksum must include all of the kernel, initramfs and devicetree contents.
+OSTree will use this to determine which kernels are shared. The rationale for
+this is to avoid computing checksums on the client by default.
The deployment should not have a traditional UNIX `/etc`; instead, it
should include `/usr/etc`. This is the "default configuration". When
}
/* Try a hardlink if we can, otherwise fall back to copying. Used
- * right now for kernels/initramfs in /boot, where we can just
+ * right now for kernels/initramfs/device trees in /boot, where we can just
* hardlink if we're on the same partition.
*/
static gboolean
char *kernel_namever;
char *initramfs_srcpath;
char *initramfs_namever;
+ char *devicetree_srcpath;
+ char *devicetree_namever;
char *bootcsum;
} OstreeKernelLayout;
static void
g_free (layout->kernel_namever);
g_free (layout->initramfs_srcpath);
g_free (layout->initramfs_namever);
+ g_free (layout->devicetree_srcpath);
+ g_free (layout->devicetree_namever);
g_free (layout->bootcsum);
g_free (layout);
}
if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
return FALSE;
}
+ g_clear_object (&in);
+ glnx_close_fd (&fd);
+
+ if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error))
+ return FALSE;
+ if (fd != -1)
+ {
+ ret_layout->devicetree_srcpath = g_strdup ("devicetree");
+ ret_layout->devicetree_namever = g_strdup_printf ("devicetree-%s", kver);
+ in = g_unix_input_stream_new (fd, FALSE);
+ if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error))
+ return FALSE;
+ }
+
+ g_clear_object (&in);
+ glnx_close_fd (&fd);
char hexdigest[OSTREE_SHA256_STRING_LEN+1];
ot_checksum_get_hexdigest (&checksum, hexdigest, sizeof (hexdigest));
const char *legacy_paths[] = {"usr/lib/ostree-boot", "boot"};
g_autofree char *kernel_checksum = NULL;
g_autofree char *initramfs_checksum = NULL;
+ g_autofree char *devicetree_checksum = NULL;
g_autoptr(OstreeKernelLayout) ret_layout = _ostree_kernel_layout_new ();
for (guint i = 0; i < G_N_ELEMENTS (legacy_paths); i++)
ret_layout->initramfs_namever = g_strndup (name, dash - name);
}
}
+ /* See if this is the devicetree */
+ else if (ret_layout->devicetree_srcpath == NULL && g_str_has_prefix (name, "devicetree-"))
+ {
+ const char *dash = strrchr (name, '-');
+ g_assert (dash);
+ if (ostree_validate_structureof_checksum_string (dash + 1, NULL))
+ {
+ devicetree_checksum = g_strdup (dash + 1);
+ ret_layout->devicetree_srcpath = g_strdup (name);
+ ret_layout->devicetree_namever = g_strndup (name, dash - name);
+ }
+ }
- /* If we found both a kernel and initramfs, break out of the loop */
- if (ret_layout->kernel_srcpath != NULL && ret_layout->initramfs_srcpath != NULL)
+ /* If we found a kernel, an initramfs and a devicetree, break out of the loop */
+ if (ret_layout->kernel_srcpath != NULL &&
+ ret_layout->initramfs_srcpath != NULL &&
+ ret_layout->devicetree_srcpath != NULL)
break;
}
return glnx_throw (error, "Mismatched kernel checksum vs initrd");
}
+ /* The kernel/devicetree checksums must be the same */
+ if (ret_layout->devicetree_srcpath != NULL)
+ {
+ g_assert (kernel_checksum != NULL);
+ g_assert (devicetree_checksum != NULL);
+ if (strcmp (kernel_checksum, devicetree_checksum) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ "Mismatched kernel checksum vs device tree in tree");
+ return FALSE;
+ }
+ }
+
ret_layout->bootcsum = g_steal_pointer (&kernel_checksum);
*out_layout = g_steal_pointer (&ret_layout);
&deployment_dfd, error))
return FALSE;
- /* Find the kernel/initramfs in the tree */
+ /* Find the kernel/initramfs/devicetree in the tree */
g_autoptr(OstreeKernelLayout) kernel_layout = NULL;
if (!get_kernel_from_tree (deployment_dfd, &kernel_layout,
cancellable, error))
}
}
+ 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 (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath,
+ bootcsum_dfd, kernel_layout->devicetree_namever,
+ sysroot->debug_flags,
+ cancellable, error))
+ return FALSE;
+ }
+ }
+
g_autofree char *contents = NULL;
if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/lib/os-release", &stbuf, 0, error))
return FALSE;
_ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg));
}
+ if (kernel_layout->devicetree_namever)
+ {
+ g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL);
+ ostree_bootconfig_parser_set (bootconfig, "devicetree", 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",
new_bootversion, osname, bootcsum,
. $(dirname $0)/libtest.sh
-echo "1..7"
+echo "1..10"
setup_os_repository "archive-z2" "uboot"
pull_test_tree() {
kernel_contents=$1
initramfs_contents=$2
+ devicetree_contents=$3
- printf "TEST SETUP:\n kernel: %s\n initramfs: %s\n layout: %s\n" \
- "$kernel_contents" "$initramfs_contents" "$layout"
+ printf "TEST SETUP:\n kernel: %s\n initramfs: %s\n devicetree: %s\n layout: %s\n" \
+ "$kernel_contents" "$initramfs_contents" "$devicetree_contents" "$layout"
- rm -rf ${test_tmpdir}/osdata/usr/lib/modules/3.6.0/{initramfs.img,vmlinuz} \
+ rm -rf ${test_tmpdir}/osdata/usr/lib/modules/3.6.0/{initramfs.img,vmlinuz,devicetree} \
${test_tmpdir}/osdata/usr/lib/ostree-boot \
${test_tmpdir}/osdata/boot
if [ "$layout" = "/usr/lib/modules" ]; then
cd ${test_tmpdir}/osdata/usr/lib/modules/3.6.0
echo -n "$kernel_contents" > vmlinuz
[ -n "$initramfs_contents" ] && echo -n "$initramfs_contents" > initramfs.img
+ [ -n "$devicetree_contents" ] && echo -n "$devicetree_contents" > devicetree
elif [ "$layout" = "/usr/lib/ostree-boot" ] || [ "$layout" = "/boot" ]; then
# "Legacy" layout
mkdir -p "${test_tmpdir}/osdata/$layout"
cd "${test_tmpdir}/osdata/$layout"
- bootcsum=$(echo -n "$kernel_contents$initramfs_contents" \
+ bootcsum=$(echo -n "$kernel_contents$initramfs_contents$devicetree_contents" \
| sha256sum | cut -f 1 -d ' ')
echo -n "$kernel_contents" > vmlinuz-${bootcsum}
[ -n "$initramfs_contents" ] && echo -n "$initramfs_contents" > initramfs-${bootcsum}
+ [ -n "$devicetree_contents" ] && echo -n "$devicetree_contents" > devicetree-${bootcsum}
else
exit 1
fi
assert_not_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'init='
echo "ok switching from no initramfs to initramfs enabled sysroot layout=$layout"
+
+ pull_test_tree "the kernel" "" "my .dtb file"
+ ${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmaster/x86_64-runtime
+
+ assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'init='
+ assert_file_has_content sysroot/boot/"$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-testos-0.conf 'devicetree')" "my .dtb file"
+ assert_not_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'initrd'
+
+ echo "ok switching from initramfs to no initramfs sysroot with devicetree layout=$layout"
done