Пример #1
0
/**
 * Read \a _buf lenght \a size byte from serial flash memmory.
 *
 * For read in serial flash memory we
 * enble cs pin and send one byte of read opcode,
 * and then 3 byte of address of memory cell we
 * want to read. After the last byte of address we
 * can read data from so pin.
 *
 * \return the number of bytes read.
 */
static size_t flash25_read(struct KFile *_fd, void *buf, size_t size)
{
	uint8_t *data = (uint8_t *)buf;

	Flash25 *fd = FLASH25_CAST(_fd);

	ASSERT(fd->fd.seek_pos + (kfile_off_t)size <= fd->fd.size);
	size = MIN((kfile_off_t)size, fd->fd.size - fd->fd.seek_pos);

	//kprintf("Reading at addr[%lu], size[%d]\n", fd->seek_pos, size);
	SS_ACTIVE();

	kfile_putc(FLASH25_READ, fd->channel);


	/*
	 * Address that we want to read.
	 */
	kfile_putc((fd->fd.seek_pos >> 16) & 0xFF, fd->channel);
	kfile_putc((fd->fd.seek_pos >> 8) & 0xFF, fd->channel);
	kfile_putc(fd->fd.seek_pos & 0xFF, fd->channel);

	kfile_read(fd->channel, data, size);

	SS_INACTIVE();

	fd->fd.seek_pos += size;

	return size;
}
Пример #2
0
/**
 * Generic getc() implementation using \a fd->read.
 */
int kfile_getc(struct KFile *fd)
{
	unsigned char c;

	if (kfile_read(fd, &c, sizeof(c)) == sizeof(c))
		return (int)((unsigned char)c);
	else
		return EOF;
}
Пример #3
0
/**
 * KFile read/write subtest.
 * Try to write/read in the same \a f file location \a size bytes.
 * \return true if all is ok, false otherwise
 * \note Restore file position at exit (if no error)
 * \note Test buffer \a buf must be filled with
 * the following statement:
 * \code
 * buf[i] = i & 0xff
 * \endcode
 */
static bool kfile_rwTest(KFile *f, uint8_t *buf, size_t size)
{
	/*
	 * Write test buffer
	 */
	if (kfile_write(f, buf, size) != size)
	{
		LOG_ERR("error writing buf");
		return false;
	}

	kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR);

	/*
	 * Reset test buffer
	 */
	memset(buf, 0, size);

	/*
	 * Read file in test buffer
	 */
	if (kfile_read(f, buf, size) != size)
	{
		LOG_ERR("error reading buf");
		return false;
	}


	kfile_seek(f, -(kfile_off_t)size, KSM_SEEK_CUR);

	/*
	 * Check test result
	 */
	for (size_t i = 0; i < size; i++)
	{
		if (buf[i] != (i & 0xff))
		{
			LOG_ERR("error comparing at index [%d] read [%02x] expected [%02x]\n", i, buf[i], i);
			return false;
		}
	}

	return true;
}
Пример #4
0
kfile_off_t kfile_copy(KFile *src, KFile *dst, kfile_off_t size)
{
	char buf[32];
	kfile_off_t cp_len = 0;

	while (size)
	{
		size_t len = MIN(sizeof(buf), (size_t)size);
		if (kfile_read(src, buf, len) != len)
			break;

		size_t wr_len = kfile_write(dst, buf, len);
		cp_len += wr_len;
		size -= len;

		if (wr_len != len)
			break;
	}

	return cp_len;
}
Пример #5
0
/**
 * \brief Transmit some data using the XModem protocol.
 *
 * \param ch Channel to use for transfer
 * \param fd Source file
 *
 * \note This function allocates a large amount of stack for
 *       the XModem transfer buffer (\see XM_BUFSIZE).
 */
bool xmodem_send(KFile *ch, KFile *fd)
{
    char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */
    size_t size = -1;
    int blocknr = 1, retries = 0, c, i;
    bool proceed, usecrc = false;
    uint16_t crc;
    uint8_t sum;

    /*
     * Reading a block can be very slow, so we read the first block early
     * to avoid receiving double XM_C char.
     * This could happen if we check for XM_C and then read the block, giving
     * the receiving device time to send another XM_C char misinterpretating
     * the blocks sent.
     */
    size = kfile_read(fd, block_buffer, XM_BUFSIZE);

    kfile_clearerr(ch);
    LOG_INFO("Wait remote host\n");

    for(;;)
    {
        proceed = false;
        do
        {
            if (XMODEM_CHECK_ABORT)
                return false;

            switch (c = kfile_getc(ch))
            {
            case XM_NAK:
                LOG_INFO("Resend blk %d\n", blocknr);
                proceed = true;
                break;

            case XM_C:
                if (c == XM_C)
                {
                    LOG_INFO("Tx start (CRC)\n");
                    usecrc = true;
                }
                else
                {
                    LOG_INFO("Tx start (BCC)\n");
                }

                proceed = true;
                break;

            case XM_ACK:
                /* End of transfer? */
                if (!size)
                    return true;

                /* Call user function to read in one block */
                size = kfile_read(fd, block_buffer, XM_BUFSIZE);
                LOG_INFO("Send blk %d\n", blocknr);
                blocknr++;
                retries = 0;
                proceed = true;
                break;

            case EOF:
                kfile_clearerr(ch);
                retries++;
                LOG_INFO("Retries %d\n", retries);
                if (retries <= CONFIG_XMODEM_MAXRETRIES)
                    break;
            /* falling through! */

            case XM_CAN:
                LOG_INFO("Transfer aborted\n");
                return false;

            default:
                LOG_INFO("Skipping garbage\n");
                break;
            }
        }
        while (!proceed);

        if (!size)
        {
            kfile_putc(XM_EOT, ch);
            continue;
        }

        /* Pad block with 0xFF if it's partially full */
        memset(block_buffer + size, 0xFF, XM_BUFSIZE - size);

        /* Send block header (STX, blocknr, ~blocknr) */
#if XM_BUFSIZE == 128
        kfile_putc(XM_SOH, ch);
#else
        kfile_putc(XM_STX, ch);
#endif
        kfile_putc(blocknr & 0xFF, ch);
        kfile_putc(~blocknr & 0xFF, ch);

        /* Send block and compute its CRC/checksum */
        sum = 0;
        crc = 0;
        for (i = 0; i < XM_BUFSIZE; i++)
        {
            kfile_putc(block_buffer[i], ch);
            crc = UPDCRC16(block_buffer[i], crc);
            sum += block_buffer[i];
        }

        /* Send CRC/Checksum */
        if (usecrc)
        {
            kfile_putc(crc >> 8, ch);
            kfile_putc(crc & 0xFF, ch);
        }
        else
            kfile_putc(sum, ch);
    }
Пример #6
0
/*
 * ext3301: modified to encrypt/decrypt files moving to/from
 * 	an encrypted folder.
 * Rename still succeeds if an encrypt/decrypt operation fails.
 */
static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
	struct inode * new_dir,	struct dentry * new_dentry )
{
	struct inode * old_inode = old_dentry->d_inode;
	struct inode * new_inode = new_dentry->d_inode;
	struct page * dir_page = NULL;
	struct ext2_dir_entry_2 * dir_de = NULL;
	struct page * old_page;
	struct ext2_dir_entry_2 * old_de;
	int err = -ENOENT;

	bool is_encryptable, src_encrypt, dest_encrypt;
	int i;
	struct file * fcrypt;
	ssize_t nchunk, nread, nwritten;
	loff_t fpos, fseekpos;
	unsigned int fsize, fremaining;
	char * buf, * strbuf1, * strbuf2, * path_src, * path_dest;
	size_t blocksize = INODE_BLKSIZE(old_inode);

	//

	dquot_initialize(old_dir);
	dquot_initialize(new_dir);

	old_de = ext2_find_entry (old_dir, &old_dentry->d_name, &old_page);
	if (!old_de)
		goto out;

	if (S_ISDIR(old_inode->i_mode)) {
		err = -EIO;
		dir_de = ext2_dotdot(old_inode, &dir_page);
		if (!dir_de)
			goto out_old;
	}

	if (new_inode) {
		struct page *new_page;
		struct ext2_dir_entry_2 *new_de;

		err = -ENOTEMPTY;
		if (dir_de && !ext2_empty_dir (new_inode))
			goto out_dir;

		err = -ENOENT;
		new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page);
		if (!new_de)
			goto out_dir;
		ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
		new_inode->i_ctime = CURRENT_TIME_SEC;
		if (dir_de)
			drop_nlink(new_inode);
		inode_dec_link_count(new_inode);
	} else {
		err = ext2_add_link(new_dentry, old_inode);
		if (err)
			goto out_dir;
		if (dir_de)
			inode_inc_link_count(new_dir);
	}

	// allocate buffers
	strbuf1 = kmalloc((size_t)512, GFP_KERNEL);
	strbuf2 = kmalloc((size_t)512, GFP_KERNEL);
	buf = kmalloc(blocksize, GFP_KERNEL);
	if (!buf || !strbuf1 || !strbuf2)
		return -ENOMEM;

	// check if the source XOR destination lie under /encrypt,
	// 	and both entries are regular or immediate files
	is_encryptable = (I_ISIM(old_inode) || I_ISREG(old_inode));
	src_encrypt = ext3301_isencrypted(old_dentry);
	dest_encrypt = ext3301_isencrypted(new_dentry);
	path_src  = ext3301_getpath(old_dentry, strbuf1, blocksize);
	path_dest = ext3301_getpath(new_dentry, strbuf2, blocksize);

	// decide whether to encrypt
	dbg(KERN_DEBUG "rename (%s --> %s)\n", path_src, path_dest);
	if (is_encryptable) {
		dbg_cr(KERN_DEBUG "- File encryptable type (regular/immediate)\n");
		if (src_encrypt && dest_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving inside /encrypt (no change))\n");
		} else if (src_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving out of /encrypt. Decrypting..\n");
			goto cryptstart;
		} else if (dest_encrypt) {
			dbg_cr(KERN_DEBUG "- File moving into /encrypt. Encrypting..\n");
			goto cryptstart;
		} else {
			dbg_cr(KERN_DEBUG "- Src/dest directories not encryptable\n");
		}
	} else {
		dbg_cr(KERN_DEBUG "- File not an encryptable type\n");
	}
	goto cryptdone;

/* encrypt/decrypt file */
cryptstart: 
	// open file
	if (!path_src)
		goto cryptfail;
	fcrypt = kfile_open(path_src, O_RDWR);
	if (!fcrypt)
		goto cryptfail;
	fsize = FILP_FSIZE(fcrypt);
	fremaining = fsize;
	fpos = 0;
	fseekpos = 0;
	dbg_cr(KERN_DEBUG " - Opened %s (Fsize: %d)\n", 
		FILP_NAME(fcrypt), fsize);
	// special case: nothing to encrypt
	if (fsize==0) 
		goto cryptclose;
	// loop: read, encrypt, write
	while (fremaining > 0) {
		// choose a chunk size
		nchunk = (fremaining > blocksize ? blocksize : (ssize_t)fremaining);
		dbg_cr(KERN_DEBUG " - Starting a %d-byte chunk at pos %u.\n", 
			(int)nchunk, (unsigned int)fpos);
		// read a chunk; make sure we read all bytes requested.
		fpos = fseekpos;
		nread = kfile_read(fcrypt, buf, (size_t)nchunk, &fpos);
		//	this inequality covers error conditions (nread<0) and 
		//	partial reads (0<=nread<=nchunk && nread != nchunk)
		if (nread != nchunk) {
			kfile_close(fcrypt);
			goto cryptfail;
		}
		// encrypt the buffer
		for (i=0; i<nchunk; i++)
			buf[i] ^= crypter_key;
		// write the chunk back
		fpos = fseekpos;
		nwritten = kfile_write(fcrypt, buf, (size_t)nchunk, &fpos);
		if (nwritten != nchunk) {
			kfile_close(fcrypt);
			goto cryptfail;
		}
		// move the file marker forward, decrease the #bytes remaining
		fseekpos += nchunk;
		fremaining -= nchunk;
	}
	// sync the read/write operations to disk. Very important!
	kfile_sync(fcrypt);

cryptclose:
	kfile_close(fcrypt);
	goto cryptdone;

cryptfail:
	// encrypt/decrypt failed
	if (dest_encrypt)
		printk(KERN_WARNING "Crypting file entering /%s failed: ino %lu\n",
				crypter_dir, INODE_INO(old_inode));
	else if (src_encrypt)
		printk(KERN_WARNING "Decrypting file leaving /%s failed: ino %lu\n",
				crypter_dir, INODE_INO(old_inode));
	goto cryptdone;

cryptdone:
	/*
	 * Like most other Unix systems, set the ctime for inodes on a
 	 * rename.
	 */
	old_inode->i_ctime = CURRENT_TIME_SEC;
	mark_inode_dirty(old_inode);

	ext2_delete_entry (old_de, old_page);

	if (dir_de) {
		if (old_dir != new_dir)
			ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0);
		else {
			kunmap(dir_page);
			page_cache_release(dir_page);
		}
		inode_dec_link_count(old_dir);
	}
	goto out_free;

out_dir:
	if (dir_de) {
		kunmap(dir_page);
		page_cache_release(dir_page);
	}
out_old:
	kunmap(old_page);
	page_cache_release(old_page);
out:
	return err;
out_free:
	// free buffers
	kfree(strbuf1);
	kfree(strbuf2);
	kfree(buf);
	return 0;
}
Пример #7
0
/**
 * KFile read/write test.
 * This function write and read \a test_buf long \a size
 * on \a fd handler.
 * \a save_buf can be NULL or a buffer where to save previous file content.
 */
int kfile_testRunGeneric(KFile *fd, uint8_t *test_buf, uint8_t *save_buf, size_t size)
{

	/*
	 * Part of test buf size that you would write.
	 * This var is used in test 3 to check kfile_write
	 * when writing beyond filesize limit.
	 */
	kfile_off_t len = size / 2;


	/* Fill test buffer */
	for (size_t i = 0; i < size; i++)
		test_buf[i] = (i & 0xff);

	/*
	 * If necessary, user can save content,
	 * for later restore.
	 */
	if (save_buf)
	{
		LOG_INFO("Saved content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + size);
		kfile_read(fd, save_buf, size);
	}

	/* TEST 1 BEGIN. */
	LOG_INFO("Test 1: write from pos 0 to [%ld]\n", (long)size);

	/*
	 * Seek to addr 0.
	 */
	if (kfile_seek(fd, 0, KSM_SEEK_SET) != 0)
		goto kfile_test_end;

	/*
	 * Test read/write to address 0..size
	 */
	if (!kfile_rwTest(fd, test_buf, size))
		goto kfile_test_end;

	LOG_INFO("Test 1: ok!\n");

	/*
	 * Restore previous read content.
	 */
	if (save_buf)
	{
		kfile_seek(fd, 0, KSM_SEEK_SET);

		if (kfile_write(fd, save_buf, size) != size)
			goto kfile_test_end;

		LOG_INFO("Restore content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + size);
	}
	/* TEST 1 END. */

	/* TEST 2 BEGIN. */
	LOG_INFO("Test 2: write from pos [%ld] to [%ld]\n", fd->size/2 , fd->size/2 + size);

	/*
	 * Go to half test size.
	 */
	kfile_seek(fd, (fd->size / 2), KSM_SEEK_SET);

	/*
	 * If necessary, user can save content
	 * for later restore.
	 */
	if (save_buf)
	{
		kfile_read(fd, save_buf, size);
		kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR);
		LOG_INFO("Saved content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + size);
	}

	/*
	 * Test read/write to address filesize/2 ... filesize/2 + size
	 */
	if (!kfile_rwTest(fd, test_buf, size))
		goto kfile_test_end;

	LOG_INFO("Test 2: ok!\n");

	/*
	 * Restore previous content.
	 */
	if (save_buf)
	{
		kfile_seek(fd, -(kfile_off_t)size, KSM_SEEK_CUR);

		if (kfile_write(fd, save_buf, size) != size)
			goto kfile_test_end;

		LOG_INFO("Restore content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + size);
	}

	/* TEST 2 END. */

	/* TEST 3 BEGIN. */
	LOG_INFO("Test 3: write outside of fd->size limit [%ld]\n", fd->size);

	/*
	 * Go to the Flash end
	 */
	kfile_seek(fd, -len, KSM_SEEK_END);

	/*
	 * If necessary, user can save content,
	 * for later restore.
	 */
	if (save_buf)
	{
		kfile_read(fd, save_buf, len);
		kfile_seek(fd, -len, KSM_SEEK_CUR);
		LOG_INFO("Saved content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + len);
	}

	/*
	 * Test read/write to address (filesize - size) ... filesize
	 */
	if (kfile_rwTest(fd, test_buf, size))
		goto kfile_test_end;

	kprintf("Test 3: ok!\n");

	/*
	 * Restore previous read content
	 */
	if (save_buf)
	{
		kfile_seek(fd, -len, KSM_SEEK_END);

		if ((kfile_off_t)kfile_write(fd, save_buf, len) != len)
			goto kfile_test_end;

		LOG_INFO("Restore content..form [%ld] to [%ld]\n", fd->seek_pos, fd->seek_pos + len);
	}

	/* TEST 3 END. */

	kfile_close(fd);
	return 0;

kfile_test_end:
	kfile_close(fd);
	LOG_ERR("One kfile_test failed!\n");
	return EOF;
}
Пример #8
0
/**
 * @return 1 if a valid message has been retrived, 0 on no valid message, -1
 * on parsing error.
 */
int8_t gsmSMSByIndex(gsmSMSMessage_t * msg, uint8_t index) {
	char c;
	uint8_t i;
	char buff[13];
	char *text;

	// SMS indexes are 1..10
	if (!index || index>10)
		return 0;

	// Get the SMS message by the specified index
	sprintf(buff, "AT+CMGR=%d", index);
	_gsmWriteLine(buff);
	// Example responce:
	// +CMGR: "REC READ","+393357963938","","10/12/14,22:59:15+04"<0D><0A>
	// $NUM+393473153808$NUM+3355763944$RES$MSG:PiazzaleLargo e Lungo, Milano, Italy$12345<0D>
	// <0D><0A>
	// <0D><0A>
	// 0<0D>

	//***** Reading message Type, record format:
	// +CMGR: <TYPE>
	// wherem TYPE is:
	// Type          Bytes  Description
	// "REC UNREAD"     12  Received unread messages
	// "REC READ"       10  Received read messages
	// "STO UNSENT"     12  Stored unsent messages
	// "STO SENT"       10  Stored sent messages
	// Minimum unique substring: 6 Bytes
	// Thus, to parse the actual type, we read:
	//     "+CMGR: " + 6Bytes = 13Bytes


	// Check if this message index is empty
	// In this case it is returned just "0<0D>"
	c = kfile_getc(&(gsm->fd));
	if (c == EOF)
		goto parse_error;
	if (c == '0') {
		msg->from[0] = 0;
		msg->time[0] = 0;
		msg->text[0] = 0;
		LOG_INFO("SMS, P: %d, EMPTY\n", index);
		return 0;
	}

	// Read the rest of the initial record identifier
	if (!kfile_read(&(gsm->fd), buff, 12))
		goto parse_error;

	// TODO: Parse message type
	//

	//***** Sender number
	// Scanning for second '"', than parse the sender number
	for (i=2; i; ) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			i--;
	}
	// Save the sender number, till next '"'
	for (i=0; i<15; i++) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			break;
		msg->from[i] = c;
	}
	msg->from[i] = '\0';

	//***** Timestamp parsing
	// Scanning for three '"', than parse the timestamp
	for (i=3; i; ) {
		c = kfile_getc(&(gsm->fd));
		if (c == EOF)
			goto parse_error;
		if (c=='"')
			i--;
	}
	// Save the timestamp (20 Bytes + terminator)
	if (!kfile_read(&(gsm->fd), msg->time, 20))
		goto parse_error;
	msg->time[20] = '\0';
	// Discard remaining chars till line termination ["<0D><0A>]
	if (!kfile_read(&(gsm->fd), buff, 3))
		goto parse_error;

	//***** Message parsing
	text = msg->text;
	(*text) = kfile_getc(&(gsm->fd));
	if ((*text) == EOF)
		goto parse_error;

	if ((*text) == '$') {
		// Scanning for first ':', than parse the message
		for (i=0; i<64; i++) {
			c = kfile_getc(&(gsm->fd));
			if (c == EOF)
				goto parse_error;
			if (c==':')
				break;
		}
		// Save the message
		if (_gsmRead(text, 160) == -1)
			goto parse_error;
	} else {
		// We are already at the beginning of the message,
		// save the remainder of the text
		if (_gsmRead(text+1, 159) == -1)
			goto parse_error;
	}

	LOG_INFO("SMS, P: %d, T: %s, N: %s, M: %s\n",
			index, msg->time, msg->from, msg->text);

	return 1;

parse_error:
	gsmDebug("Parse FAILED\n");
	return -1;
}