diff options
author | Jett Rink <jettrink@chromium.org> | 2018-05-16 11:53:29 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-21 21:18:02 -0700 |
commit | 70091bf0f76ccf88c2956c22cfcb3807e95e1849 (patch) | |
tree | b1d25541320728543b9ed4dda1e638081f66ebf1 /util | |
parent | 338c594ce37a22a12e8f879bf2eec55f486fd9bf (diff) | |
download | chrome-ec-70091bf0f76ccf88c2956c22cfcb3807e95e1849.tar.gz |
ite_flash: handle termination signal gracefully
Since we wait indefinitely for the ITE chip to be ready
when we are flashing it, we need to be able to handle the
console terminal signal gracefully so the host USB ports do
not get in a bad state.
BRANCH=none
BUG=none
TEST=Can exit while loop gracefully
Change-Id: Ica8e7c6c707cd58bdaa754be76fffef418d870e4
Signed-off-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1067788
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Justin TerAvest <teravest@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/iteflash.c | 146 |
1 files changed, 92 insertions, 54 deletions
diff --git a/util/iteflash.c b/util/iteflash.c index 849cd5cc49..0b246a56d4 100644 --- a/util/iteflash.c +++ b/util/iteflash.c @@ -7,8 +7,9 @@ #include <errno.h> #include <getopt.h> -#include <stdio.h> +#include <signal.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -67,6 +68,7 @@ static int usb_pid = SERVO_USB_PID; static int usb_interface = SERVO_INTERFACE; static char *usb_serial; static int flash_size; +static int exit_requested; /* debug traces : default OFF*/ static int debug; @@ -90,6 +92,10 @@ static int i2c_add_send_byte(struct ftdi_context *ftdi, uint8_t *buf, uint8_t failed_ack = 0; for (i = 0; i < tcnt; i++) { + /* If we got a termination signal, stop sending data */ + if (exit_requested) + return -1; + /* WORKAROUND: force SDA before sending the next byte */ *b++ = SET_BITS_LOW; *b++ = SDA_BIT; *b++ = SCL_BIT | SDA_BIT; /* write byte */ @@ -184,6 +190,10 @@ static int i2c_add_recv_bytes(struct ftdi_context *ftdi, uint8_t *buf, rbuf_idx = 0; do { + /* If we got a termination signal, stop sending data */ + if (exit_requested) + return -1; + ret = ftdi_read_data(ftdi, &rbuf[rbuf_idx], rcnt); if (ret < 0) { fprintf(stderr, "read byte failed\n"); @@ -513,70 +523,76 @@ static int send_special_waveform(struct ftdi_context *ftdi) printf("Waiting for the EC power-on sequence ..."); fflush(stdout); -retry: - /* Reset the FTDI into a known state */ - ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_RESET); - if (ret != 0) { - fprintf(stderr, "failed to reset FTDI\n"); - goto special_failed; - } + do { + /* Reset the FTDI into a known state */ + ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_RESET); + if (ret != 0) { + fprintf(stderr, "failed to reset FTDI\n"); + break; + } - /* - * set the clock divider, - * so we output a new bitbang value every 2.5us. - */ - ret = ftdi_set_baudrate(ftdi, 160000); - if (ret != 0) { - fprintf(stderr, "failed to set bitbang clock\n"); - goto special_failed; - } + /* + * set the clock divider, + * so we output a new bitbang value every 2.5us. + */ + ret = ftdi_set_baudrate(ftdi, 160000); + if (ret != 0) { + fprintf(stderr, "failed to set bitbang clock\n"); + break; + } - /* Enable asynchronous bit-bang mode */ - ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_BITBANG); - if (ret != 0) { - fprintf(stderr, "failed to set bitbang mode\n"); - goto special_failed; - } + /* Enable asynchronous bit-bang mode */ + ret = ftdi_set_bitmode(ftdi, 0xFF, BITMODE_BITBANG); + if (ret != 0) { + fprintf(stderr, "failed to set bitbang mode\n"); + break; + } + + /* do usb special waveform */ + wave[0] = 0x0; + ftdi_write_data(ftdi, (uint8_t *)wave, 1); + usleep(5000); - /* do usb special waveform */ + /* program each special tick */ + for (i = 0; i < TICK_COUNT; ) { + wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; + wave[i++] = SPECIAL_PATTERN_SDA_H_SCL_L; + wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; + } + wave[19] = SPECIAL_PATTERN_SDA_H_SCL_H; - wave[0] = 0x0; - ftdi_write_data(ftdi, (uint8_t *)wave, 1); - usleep(5000); + /* fill the buffer with the waveform pattern */ + for (i = TICK_COUNT; i < SPECIAL_BUFFER_SIZE / sizeof(uint64_t); + i++) + wave[i] = SPECIAL_PATTERN; - /* program each special tick */ - for (i = 0; i < TICK_COUNT; ) { - wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; - wave[i++] = SPECIAL_PATTERN_SDA_H_SCL_L; - wave[i++] = SPECIAL_PATTERN_SDA_L_SCL_L; - } - wave[19] = SPECIAL_PATTERN_SDA_H_SCL_H; + ret = ftdi_write_data(ftdi, (uint8_t *)wave, + SPECIAL_BUFFER_SIZE); + if (ret < 0) + fprintf(stderr, "Cannot output special waveform\n"); + /* clean everything to go back to regular I2C communication */ + ftdi_usb_purge_buffers(ftdi); + ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET); + config_i2c(ftdi); + ftdi_write_data(ftdi, release_lines, sizeof(release_lines)); - /* fill the buffer with the waveform pattern */ - for (i = TICK_COUNT; i < SPECIAL_BUFFER_SIZE / sizeof(uint64_t); i++) - wave[i] = SPECIAL_PATTERN; + /* wait for PLL stable for 5ms (plus remaining USB transfers) */ + usleep(10 * MSEC); - ret = ftdi_write_data(ftdi, (uint8_t *)wave, SPECIAL_BUFFER_SIZE); - if (ret < 0) - fprintf(stderr, "Cannot output special waveform\n"); + /* If we can talk to chip, then we can break the retry loop */ + ret = check_chipid(ftdi); - /* clean everything to go back to regular I2C communication */ - ftdi_usb_purge_buffers(ftdi); - ftdi_set_bitmode(ftdi, 0xff, BITMODE_RESET); - config_i2c(ftdi); - ftdi_write_data(ftdi, release_lines, sizeof(release_lines)); + if (ret != 0) + /* Sleep before next attempt */ + sleep(1); + } while (ret != 0); - /* wait for PLL stable for 5ms (plus remaining USB transfers) */ - usleep(10 * MSEC); + if (ret) + printf(" Failed!\n"); + else + printf(" Done.\n"); - /* if we cannot communicate, retry the sequence */ - if (check_chipid(ftdi) < 0) { - sleep(1); - goto retry; - } -special_failed: - printf("Done.\n"); free(wave); return ret; } @@ -1042,6 +1058,25 @@ int parse_parameters(int argc, char **argv) return flags; } +static void sighandler(int signum) +{ + printf("\nCaught signal %d: %s\nExiting...\n", + signum, sys_siglist[signum]); + ++exit_requested; +} + +static void register_sigaction(void) +{ + struct sigaction sigact; + + sigact.sa_handler = sighandler; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigaction(SIGINT, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); + sigaction(SIGQUIT, &sigact, NULL); +} + int main(int argc, char **argv) { void *hnd; @@ -1056,6 +1091,9 @@ int main(int argc, char **argv) if (hnd == NULL) return 1; + /* Register signal handler after opening USB handle. */ + register_sigaction(); + /* Trigger embedded monitor detection */ if (send_special_waveform(hnd) < 0) goto terminate; |