+
+/**
+ * Move \param *fd file seek position of \param offset bytes
+ * from current position.
+ */
+bool prog_seek(struct _KFile *fd, int32_t offset)
+{
+ ASSERT(fd->seek_pos + offset <= fd->size);
+
+ /* Bound check */
+ if (fd->seek_pos + offset > fd->size)
+ return false;
+
+ fd->seek_pos += offset;
+ kprintf("Flash seek to [%d]\n", fd->seek_pos);
+
+ return true;
+}
+
+/**
+ * Read from file \param *fd \param size bytes and put it in buffer \param *buf
+ * \return the number of bytes read.
+ */
+size_t prog_read(struct _KFile *fd, void *buf, size_t size)
+{
+ ASSERT(fd->seek_pos + size <= fd->size);
+ size = MIN((uint32_t)size, fd->size - fd->seek_pos);
+
+ kprintf("Reading at pos[%d]\n", fd->seek_pos);
+ // Flush current buffered page (if modified).
+ prog_flush();
+
+ /*
+ * AVR pointers are 16 bits wide, this hack is needed to avoid
+ * compiler warning, cause fd->seek_pos is a 32bit offset.
+ */
+ const uint8_t *pgm_addr = (const uint8_t *)0;
+ pgm_addr += fd->seek_pos;
+
+ memcpy_P(buf, pgm_addr, size);
+ fd->seek_pos += size;
+ kprintf("Read %d bytes\n", size);
+ return size;
+}
+