From e8fd2cdfa46cbf3decc6a48310b4a8aef244435b Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Thu, 17 Sep 2020 16:55:40 -0700 Subject: [PATCH] cros-ec: Restructure to allow RO update first Our update flow prior to this was: 1. On detach, reboot to RO. 2. From Old RO, Update RW. 3. Reboot to New RW 4. From New RW, Update RO. 5. Reboot to finish This flow has a flaw, which is that the Old RO may be buggy (especially during development, before it's actually locked down and actually Read-Only). This change will do the following instead: 1. On detach, do not reboot to RO if RO is writeable, and we are in RW 2. From old RW, Update RO 3. Reboot to new RO 4. From New RO, update RW 5. Reboot to finish. This has a speed advantage as well, as we save one reboot cycle (2 vs 3). --- plugins/cros-ec/fu-cros-ec-usb-device.c | 58 +++++++++++++++---------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/plugins/cros-ec/fu-cros-ec-usb-device.c b/plugins/cros-ec/fu-cros-ec-usb-device.c index 0ea509723..ee025ea0d 100644 --- a/plugins/cros-ec/fu-cros-ec-usb-device.c +++ b/plugins/cros-ec/fu-cros-ec-usb-device.c @@ -674,7 +674,10 @@ fu_cros_ec_usb_device_reset_to_ro (FuDevice *device, GError **error) gsize command_body_size = 0; gsize response_size = 1; - fu_device_set_custom_flags (device, "rebooting-to-ro"); + if (fu_device_has_custom_flag (device, "ro-written")) + fu_device_set_custom_flags (device, "ro-written,rebooting-to-ro"); + else + fu_device_set_custom_flags (device, "rebooting-to-ro"); if (!fu_cros_ec_usb_device_send_subcommand (device, subcommand, command_body, command_body_size, &response, &response_size, FALSE, error)) { @@ -739,8 +742,6 @@ fu_cros_ec_usb_device_write_firmware (FuDevice *device, g_prefix_error (error, "failed to send stay-in-ro subcommand: "); return FALSE; } - /* clear custom flags */ - fu_device_set_custom_flags (device, ""); /* flush all data from endpoint to recover in case of error */ if (!fu_cros_ec_usb_device_recovery (device, error)) { @@ -811,16 +812,22 @@ fu_cros_ec_usb_device_write_firmware (FuDevice *device, return FALSE; } - if (self->in_bootloader) - fu_device_set_custom_flags (device, "rw-written"); - else if (fu_device_has_custom_flag (device, "rw-written")) + if (self->in_bootloader) { + if (fu_device_has_custom_flag (device, "ro-written")) + fu_device_set_custom_flags (device, "ro-written,rw-written"); + else + fu_device_set_custom_flags (device, "rw-written"); + } else if (fu_device_has_custom_flag (device, "rw-written")) { fu_device_set_custom_flags (device, "ro-written,rw-written"); - else + } else { fu_device_set_custom_flags (device, "ro-written"); + } - if (fu_device_has_custom_flag (device, "rw-written") && - !fu_device_has_custom_flag (device, "ro-written")) + /* logical XOR */ + if (fu_device_has_custom_flag (device, "rw-written") != + fu_device_has_custom_flag (device, "ro-written")) fu_device_add_flag (device, FWUPD_DEVICE_FLAG_ANOTHER_WRITE_REQUIRED); + /* success */ return TRUE; } @@ -878,14 +885,15 @@ fu_cros_ec_usb_device_attach (FuDevice *device, GError **error) return TRUE; } - if (!self->in_bootloader) { - /* already in rw, so skip jump to rw */ - return TRUE; - } - fu_device_set_remove_delay (device, FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE); - fu_cros_ec_usb_device_jump_to_rw (device); - + if (fu_device_has_custom_flag (device, "ro-written") && + !fu_device_has_custom_flag (device, "rw-written")) { + if (!fu_cros_ec_usb_device_reset_to_ro (device, error)) { + return FALSE; + } + } else { + fu_cros_ec_usb_device_jump_to_rw (device); + } fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART); fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); @@ -904,17 +912,19 @@ fu_cros_ec_usb_device_detach (FuDevice *device, GError **error) if (self->in_bootloader) { g_debug ("skipping immediate reboot in case of already in bootloader"); - /* already in ro so skip reboot */ + /* in RO so skip reboot */ return TRUE; + } else if (self->targ.common.flash_protection != 0x0) { + /* in RW, and RO region is write protected, so jump to RO */ + fu_device_set_custom_flags (device, "ro-written"); + fu_device_set_remove_delay (device, FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE); + if (!fu_cros_ec_usb_device_reset_to_ro (device, error)) + return FALSE; + + fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART); + fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); } - fu_device_set_remove_delay (device, FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE); - if (!fu_cros_ec_usb_device_reset_to_ro (device, error)) - return FALSE; - - fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART); - fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG); - /* success */ return TRUE; }