static gboolean append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux *self, gboolean regenerate_default, int bootversion, GPtrArray *new_lines, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gs_unref_ptrarray GPtrArray *boostree_loader_configs = NULL; guint i; if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boostree_loader_configs, cancellable, error)) goto out; for (i = 0; i < boostree_loader_configs->len; i++) { OstreeBootconfigParser *config = boostree_loader_configs->pdata[i]; const char *val; val = ostree_bootconfig_parser_get (config, "title"); if (!val) val = "(Untitled)"; if (regenerate_default && i == 0) { g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val)); } g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val)); val = ostree_bootconfig_parser_get (config, "linux"); if (!val) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No \"linux\" key in bootloader config"); goto out; } g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val)); val = ostree_bootconfig_parser_get (config, "initrd"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val)); val = ostree_bootconfig_parser_get (config, "options"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val)); } ret = TRUE; out: return ret; }
static char * get_ostree_kernel_arg_from_config (OstreeBootconfigParser *config) { const char *options; char *ret = NULL; char **opts, **iter; options = ostree_bootconfig_parser_get (config, "options"); if (!options) return NULL; opts = g_strsplit (options, " ", -1); for (iter = opts; *iter; iter++) { const char *opt = *iter; if (g_str_has_prefix (opt, "ostree=")) { ret = g_strdup (opt + strlen ("ostree=")); break; } } g_strfreev (opts); return ret; }
static gboolean append_config_from_loader_entries (OstreeBootloaderSyslinux *self, gboolean regenerate_default, int bootversion, GPtrArray *new_lines, GCancellable *cancellable, GError **error) { g_autoptr(GPtrArray) loader_configs = NULL; if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &loader_configs, cancellable, error)) return FALSE; for (guint i = 0; i < loader_configs->len; i++) { OstreeBootconfigParser *config = loader_configs->pdata[i]; const char *val = ostree_bootconfig_parser_get (config, "title"); if (!val) val = "(Untitled)"; if (regenerate_default && i == 0) g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val)); g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val)); val = ostree_bootconfig_parser_get (config, "linux"); if (!val) return glnx_throw (error, "No \"linux\" key in bootloader config"); g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val)); val = ostree_bootconfig_parser_get (config, "initrd"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val)); val = ostree_bootconfig_parser_get (config, "devicetree"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("\tDEVICETREE %s", val)); val = ostree_bootconfig_parser_get (config, "options"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val)); } return TRUE; }
static gint compare_boot_loader_configs (OstreeBootconfigParser *a, OstreeBootconfigParser *b) { const char *a_version = ostree_bootconfig_parser_get (a, "version"); const char *b_version = ostree_bootconfig_parser_get (b, "version"); if (a_version && b_version) { int r = strverscmp (a_version, b_version); /* Reverse */ return -r; } else if (a_version) return -1; else return 1; }
static gboolean create_config_from_boot_loader_entries (OstreeBootloaderUboot *self, int bootversion, GPtrArray *new_lines, GCancellable *cancellable, GError **error) { g_autoptr(GPtrArray) boot_loader_configs = NULL; OstreeBootconfigParser *config; const char *val; g_autofree char *bootdir = NULL; if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs, cancellable, error)) return FALSE; /* U-Boot doesn't support a menu so just pick the first one since the list is ordered */ config = boot_loader_configs->pdata[0]; val = ostree_bootconfig_parser_get (config, "linux"); if (!val) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No \"linux\" key in bootloader config"); return FALSE; } g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s", val)); bootdir = strndup (val, strrchr(val, '/') - val); g_ptr_array_add (new_lines, g_strdup_printf ("bootdir=%s/", bootdir)); val = ostree_bootconfig_parser_get (config, "initrd"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s", val)); val = ostree_bootconfig_parser_get (config, "options"); if (val) g_ptr_array_add (new_lines, g_strdup_printf ("bootargs=%s", val)); return TRUE; }
static gint compare_deployments_by_boot_loader_version_reversed (gconstpointer a_pp, gconstpointer b_pp) { OstreeDeployment *a = *((OstreeDeployment**)a_pp); OstreeDeployment *b = *((OstreeDeployment**)b_pp); OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a); OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b); const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version"); const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version"); if (a_version && b_version) { int r = strverscmp (a_version, b_version); /* Reverse */ return -r; } else if (a_version) return -1; else return 1; }
gboolean ot_admin_instutil_builtin_set_kargs (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint i; g_autoptr(GPtrArray) deployments = NULL; OstreeDeployment *first_deployment = NULL; GOptionContext *context = NULL; glnx_unref_object OstreeSysroot *sysroot = NULL; __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; context = g_option_context_new ("ARGS - set new kernel command line arguments"); if (!ostree_admin_option_context_parse (context, options, &argc, &argv, OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, &sysroot, cancellable, error)) goto out; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; deployments = ostree_sysroot_get_deployments (sysroot); if (deployments->len == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unable to find a deployment in sysroot"); goto out; } first_deployment = deployments->pdata[0]; kargs = _ostree_kernel_args_new (); /* If they want the current kernel's args, they very likely don't * want the ones from the merge. */ if (opt_proc_cmdline) { if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) goto out; } else if (opt_merge) { OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (first_deployment); g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); _ostree_kernel_args_append_argv (kargs, previous_args); } if (opt_replace) { _ostree_kernel_args_replace_argv (kargs, opt_replace); } if (opt_append) { _ostree_kernel_args_append_argv (kargs, opt_append); } for (i = 1; i < argc; i++) _ostree_kernel_args_append (kargs, argv[i]); { g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment, kargs_strv, cancellable, error)) goto out; } ret = TRUE; out: if (context) g_option_context_free (context); return ret; }
gboolean _ostree_bootloader_grub2_generate_config (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GString *output = g_string_new (""); gs_unref_object GOutputStream *out_stream = NULL; gs_unref_ptrarray GPtrArray *loader_configs = NULL; guint i; gsize bytes_written; gboolean is_efi; /* So... yeah. Just going to hardcode these. */ static const char hardcoded_video[] = "load_video\n" "set gfxpayload=keep\n"; static const char hardcoded_insmods[] = "insmod gzio\n"; const char *grub2_boot_device_id = g_getenv ("GRUB2_BOOT_DEVICE_ID"); const char *grub2_prepare_root_cache = g_getenv ("GRUB2_PREPARE_ROOT_CACHE"); /* We must have been called via the wrapper script */ g_assert (grub2_boot_device_id != NULL); g_assert (grub2_prepare_root_cache != NULL); /* Passed from the parent */ is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL; out_stream = g_unix_output_stream_new (target_fd, FALSE); if (!_ostree_sysroot_read_boot_loader_configs (sysroot, bootversion, &loader_configs, cancellable, error)) goto out; for (i = 0; i < loader_configs->len; i++) { OstreeBootconfigParser *config = loader_configs->pdata[i]; const char *title; const char *options; const char *kernel; const char *initrd; char *quoted_title = NULL; char *uuid = NULL; char *quoted_uuid = NULL; title = ostree_bootconfig_parser_get (config, "title"); if (!title) title = "(Untitled)"; kernel = ostree_bootconfig_parser_get (config, "linux"); quoted_title = g_shell_quote (title); uuid = g_strdup_printf ("ostree-%u-%s", (guint)i, grub2_boot_device_id); quoted_uuid = g_shell_quote (uuid); g_string_append_printf (output, "menuentry %s --class gnu-linux --class gnu --class os --unrestricted %s {\n", quoted_title, quoted_uuid); g_free (uuid); g_free (quoted_title); g_free (quoted_uuid); /* Hardcoded sections */ g_string_append (output, hardcoded_video); g_string_append (output, hardcoded_insmods); g_string_append (output, grub2_prepare_root_cache); g_string_append_c (output, '\n'); if (!kernel) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No \"linux\" key in bootloader config"); goto out; } if (is_efi) g_string_append (output, "linuxefi "); else g_string_append (output, "linux16 "); g_string_append (output, kernel); options = ostree_bootconfig_parser_get (config, "options"); if (options) { g_string_append_c (output, ' '); g_string_append (output, options); } g_string_append_c (output, '\n'); initrd = ostree_bootconfig_parser_get (config, "initrd"); if (initrd) { if (is_efi) g_string_append (output, "initrdefi "); else g_string_append (output, "initrd16 "); g_string_append (output, initrd); g_string_append_c (output, '\n'); } g_string_append (output, "}\n"); } if (!g_output_stream_write_all (out_stream, output->str, output->len, &bytes_written, cancellable, error)) goto out; ret = TRUE; out: if (output) g_string_free (output, TRUE); return ret; }
gboolean ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; const char *refspec; GOptionContext *context; GKeyFile *origin = NULL; gs_unref_object OstreeRepo *repo = NULL; gs_unref_ptrarray GPtrArray *new_deployments = NULL; gs_unref_object OstreeDeployment *new_deployment = NULL; gs_unref_object OstreeDeployment *merge_deployment = NULL; gs_free char *revision = NULL; __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; context = g_option_context_new ("REFSPEC - Checkout revision REFSPEC as the new default deployment"); g_option_context_add_main_entries (context, options, NULL); if (!g_option_context_parse (context, &argc, &argv, error)) goto out; if (argc < 2) { ot_util_usage_error (context, "REF/REV must be specified", error); goto out; } refspec = argv[1]; if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error)) goto out; /* Find the currently booted deployment, if any; we will ensure it * is present in the new deployment list. */ if (!ot_admin_require_booted_deployment_or_osname (sysroot, opt_osname, cancellable, error)) { g_prefix_error (error, "Looking for booted deployment: "); goto out; } if (opt_origin_path) { origin = g_key_file_new (); if (!g_key_file_load_from_file (origin, opt_origin_path, 0, error)) goto out; } else { origin = ostree_sysroot_origin_new_from_refspec (sysroot, refspec); } if (!ostree_repo_resolve_rev (repo, refspec, FALSE, &revision, error)) goto out; merge_deployment = ostree_sysroot_get_merge_deployment (sysroot, opt_osname); /* Here we perform cleanup of any leftover data from previous * partial failures. This avoids having to call gs_shutil_rm_rf() * at random points throughout the process. * * TODO: Add /ostree/transaction file, and only do this cleanup if * we find it. */ if (!ostree_sysroot_cleanup (sysroot, cancellable, error)) { g_prefix_error (error, "Performing initial cleanup: "); goto out; } kargs = _ostree_kernel_args_new (); /* If they want the current kernel's args, they very likely don't * want the ones from the merge. */ if (opt_kernel_proc_cmdline) { gs_unref_object GFile *proc_cmdline_path = g_file_new_for_path ("/proc/cmdline"); gs_free char *proc_cmdline = NULL; gsize proc_cmdline_len = 0; gs_strfreev char **proc_cmdline_args = NULL; if (!g_file_load_contents (proc_cmdline_path, cancellable, &proc_cmdline, &proc_cmdline_len, NULL, error)) goto out; g_strchomp (proc_cmdline); proc_cmdline_args = g_strsplit (proc_cmdline, " ", -1); _ostree_kernel_args_replace_argv (kargs, proc_cmdline_args); } else if (merge_deployment) { OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); gs_strfreev char **previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); _ostree_kernel_args_replace_argv (kargs, previous_args); } if (opt_kernel_argv) { _ostree_kernel_args_replace_argv (kargs, opt_kernel_argv); } if (opt_kernel_argv_append) { _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); } { gs_strfreev char **kargs_strv = _ostree_kernel_args_to_strv (kargs); if (!ostree_sysroot_deploy_tree (sysroot, opt_osname, revision, origin, merge_deployment, kargs_strv, &new_deployment, cancellable, error)) goto out; } if (!ostree_sysroot_simple_write_deployment (sysroot, opt_osname, new_deployment, merge_deployment, opt_retain ? OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN : 0, cancellable, error)) goto out; ret = TRUE; out: if (origin) g_key_file_unref (origin); if (context) g_option_context_free (context); return ret; }