Esempio n. 1
0
/**
 * Initialize the signal handlers, catch
 * those signals we are interested in and sets SIGPIPE to be ignored.
 * @return true if initialization was sucessful.
 */
bool
Signals_Init(void)
{
    size_t i;
#ifdef HAVE_SIGACTION
    struct sigaction saction;
#endif
    if (signalpipe[0] > 0 || signalpipe[1] > 0)
        return true;

    if (pipe(signalpipe))
        return false;

    if (!io_setnonblock(signalpipe[0]) ||
            !io_setnonblock(signalpipe[1]))
        return false;
    if (!io_setcloexec(signalpipe[0]) ||
            !io_setcloexec(signalpipe[1]))
        return false;
#ifdef HAVE_SIGACTION
    memset( &saction, 0, sizeof( saction ));
    saction.sa_handler = Signal_Handler;
#ifdef SA_RESTART
    saction.sa_flags |= SA_RESTART;
#endif
#ifdef SA_NOCLDWAIT
    saction.sa_flags |= SA_NOCLDWAIT;
#endif

    for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        sigaction(signals_catch[i], &saction, NULL);

    /* we handle write errors properly; ignore SIGPIPE */
    saction.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &saction, NULL);
#else
    for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        signal(signals_catch[i], Signal_Handler);

    signal(SIGPIPE, SIG_IGN);
#endif
    return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
} /* Signals_Init */
Esempio n. 2
0
/**
 * Restores signals to their default behaviour.
 *
 * This should be called after a fork() in the new
 * child prodcess, especially when we are about to call
 * 3rd party code (e.g. PAM).
 */
void
Signals_Exit(void)
{
    size_t i;
#ifdef HAVE_SIGACTION
    struct sigaction saction;

    memset(&saction, 0, sizeof(saction));
    saction.sa_handler = SIG_DFL;

    for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        sigaction(signals_catch[i], &saction, NULL);
    sigaction(SIGPIPE, &saction, NULL);
#else
    for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        signal(signals_catch[i], SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
#endif
    close(signalpipe[1]);
    close(signalpipe[0]);
    signalpipe[0] = signalpipe[1] = 0;
}
Esempio n. 3
0
static dc_status_t
dc_descriptor_iterator_next (dc_iterator_t *abstract, void *out)
{
	dc_descriptor_iterator_t *iterator = (dc_descriptor_iterator_t *) abstract;
	dc_descriptor_t **item = (dc_descriptor_t **) out;

	if (iterator->current >= C_ARRAY_SIZE (g_descriptors))
		return DC_STATUS_DONE;

	/*
	 * The explicit cast from a const to a non-const pointer is safe here. The
	 * public interface doesn't support write access, and therefore descriptor
	 * objects are always read-only. However, the cast allows to return a direct
	 * reference to the entries in the table, avoiding the overhead of
	 * allocating (and freeing) memory for a deep copy.
	 */
	*item = (dc_descriptor_t *) &g_descriptors[iterator->current++];

	return DC_STATUS_SUCCESS;
}
Esempio n. 4
0
/*
 * Think twice before modifying the code for updating the ostc firmware!
 * It has been carefully developed and tested with assistance from
 * Heinrichs-Weikamp, using a special development unit. If you start
 * experimenting with a normal unit and accidentally screw up, you might
 * brick the device permanently and turn it into an expensive
 * paperweight. You have been warned!
 */
dc_status_t
hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
{
	dc_status_t rc = DC_STATUS_SUCCESS;
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
	dc_context_t *context = (abstract ? abstract->context : NULL);

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Allocate memory for the firmware data.
	hw_ostc_firmware_t *firmware = (hw_ostc_firmware_t *) malloc (sizeof (hw_ostc_firmware_t));
	if (firmware == NULL) {
		ERROR (context, "Failed to allocate memory.");
		return DC_STATUS_NOMEMORY;
	}

	// Read the hex file.
	rc = hw_ostc_firmware_readfile (firmware, context, filename);
	if (rc != DC_STATUS_SUCCESS) {
		ERROR (context, "Failed to read the firmware file.");
		free (firmware);
		return rc;
	}

	// Temporary set a relative short timeout. The command to setup the
	// bootloader needs to be send repeatedly, until the response packet is
	// received. Thus the time between each two attempts is directly controlled
	// by the timeout value.
	serial_set_timeout (device->port, 300);

	// Setup the bootloader.
	const unsigned int baudrates[] = {19200, 115200};
	for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
		// Adjust the baudrate.
		if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
			ERROR (abstract->context, "Failed to set the terminal attributes.");
			free (firmware);
			return DC_STATUS_IO;
		}

		// Try to setup the bootloader.
		unsigned int maxretries = (i == 0 ? 1 : MAXRETRIES);
		rc = hw_ostc_firmware_setup (device, maxretries);
		if (rc == DC_STATUS_SUCCESS)
			break;
	}
	if (rc != DC_STATUS_SUCCESS) {
		ERROR (abstract->context, "Failed to setup the bootloader.");
		free (firmware);
		return rc;
	}

	// Increase the timeout again.
	serial_set_timeout (device->port, 1000);

	// Enable progress notifications.
	dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
	progress.maximum = C_ARRAY_SIZE(firmware->bitmap);
	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);

	for (unsigned int i = 0; i < C_ARRAY_SIZE(firmware->bitmap); ++i) {
		// Skip empty blocks.
		if (firmware->bitmap[i] == 0)
			continue;

		// Create the packet.
		unsigned int address = i * SZ_BLOCK;
		unsigned char packet[4 + SZ_BLOCK + 1] = {
			(address >> 16) & 0xFF,
			(address >>  8) & 0xFF,
			(address      ) & 0xFF,
			SZ_BLOCK
		};
		memcpy (packet + 4, firmware->data + address, SZ_BLOCK);
		packet[sizeof (packet) - 1] = ~checksum_add_uint8 (packet, 4 + SZ_BLOCK, 0x00) + 1;

		// Send the packet.
		rc = hw_ostc_firmware_write (device, packet, sizeof (packet));
		if (rc != DC_STATUS_SUCCESS) {
			ERROR (abstract->context, "Failed to send the packet.");
			free (firmware);
			return rc;
		}

		// Update and emit a progress event.
		progress.current = i + 1;
		device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
	}

	free (firmware);

	return DC_STATUS_SUCCESS;
}
Esempio n. 5
0
static dc_status_t
hw_ostc_firmware_readfile (hw_ostc_firmware_t *firmware, dc_context_t *context, const char *filename)
{
	dc_status_t rc = DC_STATUS_SUCCESS;

	if (firmware == NULL) {
		ERROR (context, "Invalid arguments.");
		return DC_STATUS_INVALIDARGS;
	}

	// Initialize the buffers.
	memset (firmware->data, 0xFF, sizeof (firmware->data));
	memset (firmware->bitmap, 0x00, sizeof (firmware->bitmap));

	// Open the hex file.
	dc_ihex_file_t *file = NULL;
	rc = dc_ihex_file_open (&file, context, filename);
	if (rc != DC_STATUS_SUCCESS) {
		ERROR (context, "Failed to open the hex file.");
		return rc;
	}

	// Read the hex file.
	unsigned int lba = 0;
	dc_ihex_entry_t entry;
	while ((rc = dc_ihex_file_read (file, &entry)) == DC_STATUS_SUCCESS) {
		if (entry.type == 0) {
			// Data record.
			unsigned int address = (lba << 16) + entry.address;
			if (address + entry.length > SZ_FIRMWARE) {
				WARNING (context, "Ignoring out of range record (0x%08x,%u).", address, entry.length);
				continue;
			}

			// Copy the record to the buffer.
			memcpy (firmware->data + address, entry.data, entry.length);

			// Mark the corresponding blocks in the bitmap.
			unsigned int begin = address / SZ_BLOCK;
			unsigned int end = (address + entry.length + SZ_BLOCK - 1) / SZ_BLOCK;
			for (unsigned int i = begin; i < end; ++i) {
				firmware->bitmap[i] = 1;
			}
		} else if (entry.type == 1) {
			// End of file record.
			break;
		} else if (entry.type == 4) {
			// Extended linear address record.
			lba = array_uint16_be (entry.data);
		} else {
			ERROR (context, "Unexpected record type.");
			dc_ihex_file_close (file);
			return DC_STATUS_DATAFORMAT;
		}
	}
	if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_DONE) {
		ERROR (context, "Failed to read the record.");
		dc_ihex_file_close (file);
		return rc;
	}

	// Close the file.
	dc_ihex_file_close (file);

	// Verify the presence of the first block.
	if (firmware->bitmap[0] == 0) {
		ERROR (context, "No first data block.");
		return DC_STATUS_DATAFORMAT;
	}

	// Setup the last block.
	// Copy the "goto main" instruction, stored in the first 8 bytes of the hex
	// file, to the end of the last block at address 0x17F38. This last block
	// needs to be present, regardless of whether it's included in the hex file
	// or not!
	memset (firmware->data + SZ_FIRMWARE - SZ_BLOCK, 0xFF, SZ_BLOCK - 8);
	memcpy (firmware->data + SZ_FIRMWARE - 8, firmware->data, 8);
	firmware->bitmap[C_ARRAY_SIZE(firmware->bitmap) - 1] = 1;

	// Setup the first block.
	// Copy the hardcoded "goto 0x17F40" instruction to the start of the first
	// block at address 0x00000.
	const unsigned char header[] = {0xA0, 0xEF, 0xBF, 0xF0};
	memcpy (firmware->data, header, sizeof (header));

	return rc;
}