From 8d8ac875f5b514952c02f103bdbb6482015b4ee7 Mon Sep 17 00:00:00 2001 From: Dmitry Rozhkov Date: Thu, 24 Mar 2016 10:00:29 +0200 Subject: [PATCH] swupd-client: Add ostro specific tweaks to swupd Ostro uses an update mechanism which differs from what's used in ClearLinux. This patch adds Ostro specific EFI updater to the swupd client. Signed-off-by: Dmitry Rozhkov swupd-client: add rdep on gptfdisk to satisfy EFI updater Ostro's swupd uses efi_combo_updater app to update the boot partitions. This apps relies on sgdisk presence which is a part of gptfdisk. Signed-off-by: Dmitry Rozhkov --- .../swupd-client/oe-swupd-helpers.bbappend | 3 + .../efi-combo-trigger.service | 7 + .../oe-swupd-helpers/update-triggers.target | 6 + .../0001-Disable-boot-file-heuristics.patch | 32 +++++ .../swupd-client/efi_combo_updater.c | 136 ++++++++++++++++++ .../swupd-client/swupd-client_%.bbappend | 16 +++ 6 files changed, 200 insertions(+) create mode 100644 meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers.bbappend create mode 100644 meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/efi-combo-trigger.service create mode 100644 meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/update-triggers.target create mode 100644 meta-ostro/recipes-swupd/swupd-client/swupd-client/0001-Disable-boot-file-heuristics.patch create mode 100644 meta-ostro/recipes-swupd/swupd-client/swupd-client/efi_combo_updater.c create mode 100644 meta-ostro/recipes-swupd/swupd-client/swupd-client_%.bbappend diff --git a/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers.bbappend b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers.bbappend new file mode 100644 index 00000000000..674cb5b75e3 --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers.bbappend @@ -0,0 +1,3 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = "file://efi-combo-trigger.service" diff --git a/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/efi-combo-trigger.service b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/efi-combo-trigger.service new file mode 100644 index 00000000000..fe3d81aeac4 --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/efi-combo-trigger.service @@ -0,0 +1,7 @@ +[Unit] +Description=Updates the EFI combo application +BindsTo=update-triggers.target + +[Service] +Type=oneshot +ExecStart=/usr/bin/efi_combo_updater \ No newline at end of file diff --git a/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/update-triggers.target b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/update-triggers.target new file mode 100644 index 00000000000..fde91d910ea --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/oe-swupd-helpers/update-triggers.target @@ -0,0 +1,6 @@ +[Unit] +Description=Post system update triggers +Wants=ldconfig-trigger.service +Wants=catalog-trigger.service +Wants=tmpfiles-trigger.service +Wants=efi-combo-trigger.service diff --git a/meta-ostro/recipes-swupd/swupd-client/swupd-client/0001-Disable-boot-file-heuristics.patch b/meta-ostro/recipes-swupd/swupd-client/swupd-client/0001-Disable-boot-file-heuristics.patch new file mode 100644 index 00000000000..0fb199b30bb --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/swupd-client/0001-Disable-boot-file-heuristics.patch @@ -0,0 +1,32 @@ +From 5f93d2ff31607539ce9957daf78f920e25873b4a Mon Sep 17 00:00:00 2001 +From: Dmitry Rozhkov +Date: Tue, 23 Feb 2016 17:07:30 +0200 +Subject: [PATCH] Disable boot file heuristics + +Ostro uses a mechanism different from what's used in ClearLinux +to detect changes in kernel, bootloader, initramfs. + +Upstream-Status: Inappropriate [Ostro uses different mechanism for boot file updates] + +Signed-off-by: Dmitry Rozhkov +--- + src/heuristics.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/heuristics.c b/src/heuristics.c +index 12fb59c..1e164b2 100644 +--- a/src/heuristics.c ++++ b/src/heuristics.c +@@ -107,7 +107,9 @@ static void boot_file_heuristics(struct file *file) + void apply_heuristics(struct file *file) + { + runtime_state_heuristics(file); ++#if 0 + boot_file_heuristics(file); ++#endif + config_file_heuristics(file); + } + +-- +2.5.0 + diff --git a/meta-ostro/recipes-swupd/swupd-client/swupd-client/efi_combo_updater.c b/meta-ostro/recipes-swupd/swupd-client/swupd-client/efi_combo_updater.c new file mode 100644 index 00000000000..876fee92b3c --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/swupd-client/efi_combo_updater.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + +#define OUTBUF_SIZE 4096 + +const char EFI_TYPE[] = "EF00"; +const char EFI_BACKUP_TYPE[] = "2700"; + +const char ROOT_BLOCK_DEVICE_CMD[] = + "/bin/mount |/bin/grep \"/dev/sd\" " + "|/bin/grep \"on / type\" |/bin/sed 's/[0-9].*$//'"; + +const char ROOT_BLOCK_DEVICE_SD_CMD[] = + "/bin/mount |/bin/grep \"/dev/mmcblk\" " + "|/bin/grep \"on / type\" |/bin/sed 's/p[0-9].*$//'"; + +const char EFI_PARTITION_NR_CMD[] = + "/usr/sbin/sgdisk -p %s 2> /dev/null |/bin/grep %s " + "|/bin/sed -e 's/[ ]*//' |/usr/bin/cut -d ' ' -f 1"; + +const char EFI_BACKUP_PARTITION_NR_CMD[] = + "/usr/sbin/sgdisk -p %s 2> /dev/null |/bin/grep %s " + "|/bin/sed -e 's/[ ]*//' |/usr/bin/cut -d ' ' -f 1"; + + +/* Runs a command, with optional parameters. + The combined stderr & stdout are returned through + a pointer, if provided. + The retval is the retval of the command.*/ + +int execute(char **output, const char *fmt, ...) { + va_list ap; + FILE *fp; + char *command; + static char outbuf[OUTBUF_SIZE]; + unsigned int answer_len; + int i; + + va_start(ap, fmt); + assert(vasprintf(&command, fmt, ap) > 0); + va_end(ap); + #if defined(DEBUG) + printf("COMMAND => %s\n", command); + #endif + assert(fp = popen(command, "r")); + fgets(outbuf, sizeof(outbuf)-1, fp); + if (output) { + answer_len = strnlen(outbuf, OUTBUF_SIZE - 1); + assert(answer_len <= (OUTBUF_SIZE - 1)); + for (i = 0; i <= answer_len; i++) + if (outbuf[i] == '\n') + outbuf[i] = '\0'; + #if defined(DEBUG) + printf("RESULT => %s\n" + "answer_len => %u\n", outbuf, answer_len); + #endif + if (answer_len > 1) { + *output = malloc(answer_len); + strcpy(*output, outbuf); + } + else + *output = 0; + } + free(command); + return WEXITSTATUS(pclose(fp)); +} + +int main(void) { + char *root_block_device = NULL; + char *efi_partition_nr; + char *efi_backup_partition_nr; + char part_prefix[] = { '\0', '\0'}; + unsigned int update_needed; + int retval; + + /* Identify the block device with the rootfs, which is the + same containing the EFI partitions.*/ + execute(&root_block_device, ROOT_BLOCK_DEVICE_CMD); + if (root_block_device == NULL) { + execute(&root_block_device, ROOT_BLOCK_DEVICE_SD_CMD); + *part_prefix = 'p'; + } + printf("ROOT_BLOCK_DEVICE %s\n", root_block_device); + printf("Partition prefix: \"%s\"\n", part_prefix); + + /* Identify the active EFI partition. */ + assert(execute(&efi_partition_nr, EFI_PARTITION_NR_CMD, + root_block_device, EFI_TYPE) == 0); + printf("EFI_PARTITION_NR %s\n", efi_partition_nr); + + /* Identify the inactive EFI partition. */ + assert(execute(&efi_backup_partition_nr, EFI_BACKUP_PARTITION_NR_CMD, + root_block_device, EFI_BACKUP_TYPE) == 0); + printf("EFI_BACKUP_PARTITION_NR %s\n", efi_backup_partition_nr); + + /* Cleanup possible leftovers.*/ + execute(NULL, "/bin/umount /tmp/mnt 2>&1"); + execute(NULL, "/bin/rm -rf /tmp/mnt 2>&1"); + + /* Check if the current efi combo file is up-to-date. */ + assert(execute(NULL, "/bin/mkdir /tmp/mnt 2>&1") ==0); + assert(execute(NULL, "/bin/mount %s%s%s /tmp/mnt/ 2>&1", + root_block_device, part_prefix, + efi_partition_nr) == 0); + update_needed = execute(NULL, "/usr/bin/diff /tmp/mnt/EFI/BOOT/*.efi " + "/boot/EFI/BOOT/*.efi 2>&1"); + + if (!update_needed) + return 0; + + /*Update required, so mount the inactive EFI partition.*/ + assert(execute(NULL, "/bin/umount /tmp/mnt/ 2>&1") == 0); + assert(execute(NULL, "/bin/mount %s%s%s /tmp/mnt/ 2>&1", + root_block_device, part_prefix, + efi_backup_partition_nr) == 0); + + /* Nuke the old content and deploy the new one.*/ + assert(execute(NULL, "/bin/rm /tmp/mnt/EFI/BOOT/*") == 0); + assert(execute(NULL, "/bin/sync") == 0); + assert(execute(NULL, "/bin/cp /boot/EFI/BOOT/*.efi " + "/tmp/mnt/EFI/BOOT/") == 0); + assert(execute(NULL, "/bin/sync") == 0); + assert(execute(NULL, "/bin/umount /tmp/mnt/ 2>&1") == 0); + assert(execute(NULL, "/bin/sync") == 0); + + + /* Make the inactive partition active and vice-versa.*/ + assert(execute(NULL, "/usr/sbin/sgdisk -t %s:%s -t %s:%s %s", + efi_partition_nr, EFI_BACKUP_TYPE, + efi_backup_partition_nr, EFI_TYPE, + root_block_device) == 0); + assert(execute(NULL, "/bin/sync") == 0); +} diff --git a/meta-ostro/recipes-swupd/swupd-client/swupd-client_%.bbappend b/meta-ostro/recipes-swupd/swupd-client/swupd-client_%.bbappend new file mode 100644 index 00000000000..eb6fff642f8 --- /dev/null +++ b/meta-ostro/recipes-swupd/swupd-client/swupd-client_%.bbappend @@ -0,0 +1,16 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = "file://0001-Disable-boot-file-heuristics.patch \ + file://efi_combo_updater.c \ + " + +RDEPENDS_${PN}_class-target_append = " gptfdisk" + +do_compile_append() { + ${CC} ${LDFLAGS} ${WORKDIR}/efi_combo_updater.c -Os -o ${B}/efi_combo_updater `pkg-config --cflags --libs glib-2.0` +} + +do_install_append () { + install -d ${D}/usr/bin + install ${B}/efi_combo_updater ${D}/usr/bin/ +}