diff --git a/Makefile-man.am b/Makefile-man.am
index 8ccbba8c6e..fee5b89721 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -26,7 +26,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \
ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \
ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \
ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \
-ostree-admin-pin.1 \
+ostree-admin-pin.1 ostree-admin-esp-upgrade.1 \
ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \
ostree-commit.1 ostree-create-usb.1 ostree-export.1 ostree-gpg-sign.1 \
ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \
diff --git a/Makefile-ostree.am b/Makefile-ostree.am
index 8d352e38fd..7ae761eb3b 100644
--- a/Makefile-ostree.am
+++ b/Makefile-ostree.am
@@ -79,6 +79,7 @@ ostree_SOURCES += \
src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-switch.c \
src/ostree/ot-admin-builtin-pin.c \
+ src/ostree/ot-admin-builtin-esp-upgrade.c \
src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtins.h \
diff --git a/man/ostree-admin-esp-upgrade.xml b/man/ostree-admin-esp-upgrade.xml
new file mode 100644
index 0000000000..ef6c79ed6d
--- /dev/null
+++ b/man/ostree-admin-esp-upgrade.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+ ostree admin esp-upgrade
+ OSTree
+
+
+
+ Developer
+ Javier
+ Martinez Canillas
+ javierm@redhat.com
+
+
+
+
+
+ ostree admin esp-upgrade
+ 1
+
+
+
+ ostree-admin-esp-upgrade
+ Upgrade the EFI System Partition (ESP) with files from the current deployment
+
+
+
+
+ ostree admin esp-upgrade
+
+
+
+
+ Description
+
+
+ Upgrade the EFI System Partition (ESP) with the files in the /usr/lib/ostree-boot/efi/ directory of the current deployment.
+
+
+
+
+ Example
+ $ ostree admin esp-upgrade
+
+
diff --git a/src/ostree/ot-admin-builtin-esp-upgrade.c b/src/ostree/ot-admin-builtin-esp-upgrade.c
new file mode 100644
index 0000000000..94f6a2c6dc
--- /dev/null
+++ b/src/ostree/ot-admin-builtin-esp-upgrade.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: LGPL-2.0+
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Javier Martinez Canillas
+ */
+
+#include "config.h"
+
+#include "ostree-sysroot-private.h"
+#include "ot-main.h"
+#include "ot-admin-builtins.h"
+#include "ot-admin-functions.h"
+#include "otutil.h"
+
+static GOptionEntry options[] = {
+ { NULL }
+};
+
+gboolean
+ot_admin_builtin_esp_upgrade (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
+{
+ g_autoptr(GOptionContext) context = g_option_context_new ("");
+
+ g_autoptr(OstreeSysroot) sysroot = NULL;
+ if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
+ OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
+ invocation, &sysroot, cancellable, error))
+ return FALSE;
+
+ g_autoptr(OstreeRepo) repo = NULL;
+ if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
+ return FALSE;
+
+ g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
+ OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
+
+ g_autoptr(OstreeDeployment) pending_deployment = NULL;
+ g_autoptr(OstreeDeployment) rollback_deployment = NULL;
+ if (booted_deployment)
+ ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment,
+ &rollback_deployment);
+
+ if (deployments->len == 0)
+ {
+ g_print ("No deployments.\n");
+ return TRUE;
+ }
+
+ struct stat stbuf;
+
+ if (!glnx_fstatat_allow_noent (sysroot->sysroot_fd, "/sys/firmware/efi", &stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+
+ if (errno == ENOENT)
+ {
+ g_print ("Not an EFI installation.\n");
+ return TRUE;
+ }
+
+ if (!ot_is_rw_mount ("/boot/efi"))
+ {
+ g_print ("Only ESP mounted in /boot/efi is supported.\n");
+ return TRUE;
+ }
+
+ g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (sysroot, booted_deployment);
+ g_autofree char *new_esp_path = g_strdup_printf ("%s/usr/lib/ostree-boot", deployment_path);
+
+ GLNX_AUTO_PREFIX_ERROR ("During copy files to the ESP", error);
+ glnx_autofd int old_esp_fd = -1;
+ if (!glnx_opendirat (sysroot->sysroot_fd, "/boot", TRUE, &old_esp_fd, error))
+ return FALSE;
+
+ glnx_autofd int new_esp_fd = -1;
+ if (!glnx_opendirat (sysroot->sysroot_fd, new_esp_path, TRUE, &new_esp_fd, error))
+ return FALSE;
+
+ /* The ESP filesystem is vfat so don't attempt to copy ownership, mode, and xattrs */
+ const OstreeSysrootDebugFlags flags = sysroot->debug_flags | OSTREE_SYSROOT_DEBUG_NO_XATTRS;
+
+ if (!ot_copy_dir_recurse (new_esp_fd, old_esp_fd, "efi", flags , cancellable, error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h
index d88fc0b907..5efb7101b0 100644
--- a/src/ostree/ot-admin-builtins.h
+++ b/src/ostree/ot-admin-builtins.h
@@ -40,6 +40,7 @@ BUILTINPROTO(undeploy);
BUILTINPROTO(deploy);
BUILTINPROTO(cleanup);
BUILTINPROTO(pin);
+BUILTINPROTO(esp_upgrade);
BUILTINPROTO(finalize_staged);
BUILTINPROTO(unlock);
BUILTINPROTO(status);
diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c
index 9f1a61562a..0de2ac7199 100644
--- a/src/ostree/ot-builtin-admin.c
+++ b/src/ostree/ot-builtin-admin.c
@@ -57,6 +57,9 @@ static OstreeCommand admin_subcommands[] = {
{ "pin", OSTREE_BUILTIN_FLAG_NO_REPO,
ot_admin_builtin_pin,
"Change the \"pinning\" state of a deployment" },
+ { "esp-upgrade", OSTREE_BUILTIN_FLAG_NO_REPO,
+ ot_admin_builtin_esp_upgrade,
+ "Upgrade the ESP with the files on the current deployment" },
{ "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO,
ot_admin_builtin_set_origin,
"Set Origin and create a new origin file" },