/* * Enable multiple timeouts at once. * * This works like calling enable_timeout_after() and/or enable_timeout_at() * multiple times. Use this to reduce the number of GetCurrentTimestamp() * and setitimer() calls needed to establish multiple timeouts. */ void enable_timeouts(const EnableTimeoutParams *timeouts, int count) { TimestampTz now; int i; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout(s) at the appropriate times. */ now = GetCurrentTimestamp(); for (i = 0; i < count; i++) { TimeoutId id = timeouts[i].id; TimestampTz fin_time; switch (timeouts[i].type) { case TMPARAM_AFTER: fin_time = TimestampTzPlusMilliseconds(now, timeouts[i].delay_ms); enable_timeout(id, now, fin_time); break; case TMPARAM_AT: enable_timeout(id, now, timeouts[i].fin_time); break; default: elog(ERROR, "unrecognized timeout type %d", (int) timeouts[i].type); break; } } /* Set the timer interrupt. */ schedule_alarm(now); }
/* * Enable the specified timeout to fire at the specified time. * * This is provided to support cases where there's a reason to calculate * the timeout by reference to some point other than "now". If there isn't, * use enable_timeout_after(), to avoid calling GetCurrentTimestamp() twice. */ void enable_timeout_at(TimeoutId id, TimestampTz fin_time) { TimestampTz now; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout at the appropriate time. */ now = GetCurrentTimestamp(); enable_timeout(id, now, fin_time); /* Set the timer interrupt. */ schedule_alarm(now); }
/* * Enable the specified timeout to fire after the specified delay. * * Delay is given in milliseconds. */ void enable_timeout_after(TimeoutId id, int delay_ms) { TimestampTz now; TimestampTz fin_time; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout at the appropriate time. */ now = GetCurrentTimestamp(); fin_time = TimestampTzPlusMilliseconds(now, delay_ms); enable_timeout(id, now, fin_time); /* Set the timer interrupt. */ schedule_alarm(now); }
int main(int argc, char **argv) { /*! default at failure */ int main_ret = 1; /*! input XML file, if specified */ FILE *inp_xml_file = 0; /*! output XML file, if specified */ FILE *out_xml_file = 0; /*! serial device path */ const char *serial_device_path = SERIAL_DEVICE_PATH; /*! CPI instance */ cpi_t *p_cpi = 0; /*! options for stdout */ int print_putative_id = 0; int print_all = 0; int print_usage = 0; /*! options for power down and alarm */ int do_shutdown = 0; int do_alarm = 0; uint32_t alarm_time = 0; /*! key id */ uint16_t key_id = 0; /*! raw buffer, used to parse results */ uint8_t *tmp_buffer1 = 0, *tmp_buffer2 = 0, *tmp_buffer3 = 0; /*! @hack @todo thread for monitoring timeout */ pthread_t timeout_thread; /*! initialize timeout thread */ pthread_create(&timeout_thread, 0, timeout_hack, 0); /*! print usage if there are no arguments */ if(argc <= 1) { print_usage = 1; } /*! initialize temporary buffers */ { tmp_buffer1 = (uint8_t*)malloc(CPI_MAX_RESULT_SIZE); if(tmp_buffer1 == 0) { fprintf(stderr, "Error: could not allocate %d bytes for tmp_buffer1\n", CPI_MAX_RESULT_SIZE); return 1; } tmp_buffer2 = (uint8_t*)malloc(CPI_MAX_RESULT_SIZE); if(tmp_buffer2 == 0) { fprintf(stderr, "Error: could not allocate %d bytes for tmp_buffer2\n", CPI_MAX_RESULT_SIZE); return 1; } tmp_buffer3 = (uint8_t*)malloc(CPI_MAX_RESULT_SIZE); if(tmp_buffer3 == 0) { fprintf(stderr, "Error: could not allocate %d bytes for tmp_buffer3\n", CPI_MAX_RESULT_SIZE); return 1; } } /*! parse command line */ { int cur_arg = 0; for(cur_arg = 1; cur_arg < argc; cur_arg++) { /*! expect all options to begin with '-' character */ if(argv[cur_arg][0] != '-') { fprintf(stderr, "Warning: Unrecognized option \"%s\"\n", argv[cur_arg]); continue; } /*! process command options */ switch(argv[cur_arg][1]) { case 'k': { /*! skip over to key ID */ if(++cur_arg >= argc) { break; } /*! attempt to parse key ID */ sscanf(argv[cur_arg], "%hu", &key_id); } break; case 't': { /*! Skip to port path */ if (++cur_arg >= argc) { break; } serial_device_path = argv[cur_arg]; fprintf( stderr, "Using non-default serial port %s\n", serial_device_path ); } break; case 'r': { /*! skip over to filename */ if(++cur_arg >= argc) { break; } /*! attempt to open inpt file */ inp_xml_file = fopen(argv[cur_arg], "rt"); /*! report file open error to user */ if(inp_xml_file == 0) { fprintf(stderr, "Error: Could not open \"%s\" for reading.\n", argv[cur_arg]); } } break; case 'w': { /*! skip over to filename */ if(++cur_arg >= argc) { break; } /*! attempt to open output file */ out_xml_file = fopen(argv[cur_arg], "wt"); /*! report file open error to user */ if(out_xml_file == 0) { fprintf(stderr, "Error: Could not open \"%s\" for writing\n", argv[cur_arg]); } } break; case 'i': { if(inp_xml_file == 0) { inp_xml_file = stdin; } } break; case 'o': { if(out_xml_file == 0) { out_xml_file = stdout; } } break; case 'p': print_putative_id = 1; break; case 'a': { do_alarm = 1; /*! skip over to alarm time */ if(++cur_arg >= argc) { break; } /*! attempt to parse key ID */ sscanf(argv[cur_arg], "%u", &alarm_time); } break; case 's': do_shutdown = 1; break; case 'd': print_all = 1; break; case '-': print_usage = 1; break; default: fprintf(stderr, "Warning: Unrecognized option \"%s\"\n", argv[cur_arg]); break; } } } /*! optionally, print usage */ if(print_usage) { show_usage(); goto cleanup; } /*! create CPI instance */ { cpi_info_t cpi_info = { 0 }; /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_create(&cpi_info, &p_cpi); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_create failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } } /*! initialize CPI instance */ { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_init(p_cpi, serial_device_path); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_init failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } } /*! optionally read input XML data */ if(inp_xml_file != 0) { int size = 0; /*! read up to max buffer size minus null terminator */ { size_t ret = fread(tmp_buffer1, 1, CPI_MAX_RESULT_SIZE-1, inp_xml_file); /*! update size */ if(ret > 0) { size = ret; } /*! append null terminator */ tmp_buffer1[size] = '\0'; } /*! process XML data */ { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_process_xml(p_cpi, (char*)tmp_buffer1, (char*)tmp_buffer2); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_process_xml failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } } /*! optionally write XML output */ if(out_xml_file != 0) { int size = strlen((char*)tmp_buffer2); /*! write output data to out_xml_file */ if(size > 0) { size_t ret = fwrite(tmp_buffer2, 1, size, out_xml_file); if(ret != size) { fprintf(stderr, "Error: fwrite returned %d, expected %d\n", ret, size); goto cleanup; } } } } /*! get putative ID */ if(print_all || print_putative_id) { char str[CPI_PUTATIVE_ID_SIZE]; /*!< @hack @todo enable hung CPI timeout */ enable_timeout(4); int ret = cpi_get_putative_id(p_cpi, key_id, str); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_putative_id failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } /*! print to stdout in all format */ if(print_all) { printf("Putative ID : %s\n", str); } /*! print only putative ID */ else if(print_putative_id) { printf("%s\n", str); } } /*! get public key */ if(print_all) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_public_key(p_cpi, key_id, (char*)tmp_buffer1); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_public_key failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } /*! public key contains an endline already */ printf("Public Key : \n%s", tmp_buffer1); } /*! get version data */ if(print_all) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_version_data(p_cpi, tmp_buffer1); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_version_data failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Version Data :\n"); print_raw(tmp_buffer1, CPI_VERSION_SIZE); } /*! get current time */ if(print_all) { uint32_t cur_time = 0; /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_current_time(p_cpi, &cur_time); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_current_time failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Current Time : %d seconds since last reboot\n", cur_time); } /*! get current owner key index */ if(print_all) { uint32_t cur_oki = 0; /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_owner_key_index(p_cpi, &cur_oki); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_owner_key_index failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Current Owner Key Index : %d\n", cur_oki); } /*! get serial number data */ if(print_all) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_serial_number(p_cpi, tmp_buffer1); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_serial_number failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Serial Number :\n"); print_raw(tmp_buffer1, CPI_SERIAL_NUMBER_SIZE); } /*! get hardware version data */ if(print_all) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_get_hardware_version_data(p_cpi, tmp_buffer1); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_get_hardware_version_data failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Hardware Version Data :\n"); print_raw(tmp_buffer1, CPI_HARDWARE_VERSION_SIZE); } /*! issue challenge */ if(print_all) { uint8_t rand_data[0x10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; memset(tmp_buffer1, 0, CPI_MAX_RESULT_SIZE); memset(tmp_buffer2, 0, CPI_MAX_RESULT_SIZE); memset(tmp_buffer3, 0, CPI_MAX_RESULT_SIZE); /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_issue_challenge(p_cpi, key_id, rand_data, tmp_buffer1, tmp_buffer2, tmp_buffer3); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_issue_challenge failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("result1 : \n"); /*! print result1 */ print_raw(tmp_buffer1, CPI_RESULT1_SIZE); printf("result2 : \n"); /*! print result1 */ print_raw(tmp_buffer2, CPI_RESULT2_SIZE); #if defined(CNPLATFORM_falconwing) printf("result3 : \n"); /*! print result1 */ print_raw(tmp_buffer3, CPI_RESULT3_SIZE); #endif } /*! set alarm */ if(do_alarm) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_set_alarm_time(p_cpi, alarm_time); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_set_alarm_time failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } printf("Alarm was set for %d seconds from now\n", alarm_time); } /*! optionally, power down */ if(do_shutdown) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_trigger_power_down(p_cpi); if(CPI_FAILED(ret)) { fprintf(stderr, "Error: cpi_trigger_power_down failed (%s)\n", CPI_RETURN_CODE_LOOKUP[ret]); goto cleanup; } } main_ret = 0; cleanup: /*! cleanup input file handle(s) */ if( (inp_xml_file != 0) && (inp_xml_file != stdin) ) { fclose(inp_xml_file); inp_xml_file = 0; } /*! cleanup file handle(s) */ if( (out_xml_file != 0) && (out_xml_file != stdout) ) { fclose(out_xml_file); out_xml_file = 0; } if(tmp_buffer2 != 0) { free(tmp_buffer2); tmp_buffer2 = 0; } if(tmp_buffer1 != 0) { free(tmp_buffer1); tmp_buffer1 = 0; } /*! cleanup CPI instance */ if(p_cpi != 0) { /*!< @hack @todo enable hung CPI timeout */ enable_timeout(10); int ret = cpi_close(p_cpi); if(CPI_FAILED(ret)) { fprintf(stderr, "Warning: cpi_close failed (0x%.08X)\n", ret); return 1; } } /*! cleanup timeout thread */ { timeout_hack_stop = 1; pthread_join(timeout_thread, 0); } return main_ret; }