efi-boot-generator.c revision 6d26dfe11c853d612b84abe858520bbcb62c2e96
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/***
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen This file is part of systemd.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Copyright 2013 Lennart Poettering
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is free software; you can redistribute it and/or modify it
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen under the terms of the GNU Lesser General Public License as published by
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (at your option) any later version.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is distributed in the hope that it will be useful, but
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Lesser General Public License for more details.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen You should have received a copy of the GNU Lesser General Public License
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen***/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <unistd.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include <stdlib.h>
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "efivars.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "path-util.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "util.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "mkdir.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "unit-name.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "virt.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "generator.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen#include "special.h"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic const char *arg_dest = "/tmp";
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenint main(int argc, char *argv[]) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *what = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_fclose_ FILE *f = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen int r = EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_id128_t id;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char *name;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (argc > 1 && argc != 4) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("This program takes three or no arguments.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (argc > 1)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen arg_dest = argv[3];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_set_target(LOG_TARGET_SAFE);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_parse_environment();
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_open();
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen umask(0022);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (in_initrd()) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("In initrd, exiting.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (detect_container(NULL) > 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("In a container, exiting.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!is_efi_boot()) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("Not an EFI boot, exiting.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (path_is_mount_point("/boot", true) <= 0 &&
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen dir_is_empty("/boot") <= 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("/boot already populated, exiting.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = efi_loader_get_device_part_uuid(&id);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r == -ENOENT) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_debug("EFI loader partition unknown exiting.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_SUCCESS;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen } else if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to read ESP partition UUID: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen name = strappenda(arg_dest, "/boot.mount");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen f = fopen(name, "wxe");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (!f) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to create mount unit file %s: %m", name);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = asprintf(&what,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "/dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen SD_ID128_FORMAT_VAL(id));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_oom();
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(f,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "# Automatially generated by systemd-efi-boot-generator\n\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "[Unit]\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "Description=EFI System Partition\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "Documentation=man:systemd-efi-boot-generator(8)\n");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = generator_write_fsck_deps(f, arg_dest, what, "/boot", "vfat");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fprintf(f,
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "[Mount]\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "What=%s\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "Where=/boot\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "Type=vfat\n"
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen "Options=umask=0077,noauto\n",
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen what);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fflush(f);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (ferror(f)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to write mount unit file: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen return EXIT_FAILURE;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen }
name = strappenda(arg_dest, "/boot.automount");
fclose(f);
f = fopen(name, "wxe");
if (!f) {
log_error("Failed to create automount unit file %s: %m", name);
return EXIT_FAILURE;
}
fputs("# Automatially generated by systemd-efi-boot-generator\n\n"
"[Unit]\n"
"Description=EFI System Partition Automount\n\n"
"[Automount]\n"
"Where=/boot\n", f);
fflush(f);
if (ferror(f)) {
log_error("Failed to write automount unit file: %m");
return EXIT_FAILURE;
}
name = strappenda(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/boot.automount");
mkdir_parents(name, 0755);
if (symlink("../boot.automount", name) < 0) {
log_error("Failed to create symlink %s: %m", name);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}