void SoundManager::init() {
		m_device = alcOpenDevice(NULL);

		if (!m_device || alcGetError(m_device) != ALC_NO_ERROR) {
			FL_ERR(_log, LMsg() << "Could not open audio device - deactivating audio module");
			m_device = NULL;
			return;
		}

		m_context = alcCreateContext(m_device, NULL);
		if (!m_context || alcGetError(m_device) != ALC_NO_ERROR) {
			FL_ERR(_log, LMsg() << "Couldn't create audio context - deactivating audio module");
			m_device = NULL;
			return;
		}

		alcMakeContextCurrent(m_context);
		if (alcGetError(m_device) != ALC_NO_ERROR) {
			FL_ERR(_log, LMsg() << "Couldn't change current audio context - deactivating audio module");
			m_device = NULL;
			return;
		}

		// set listener position
		alListener3f(AL_POSITION, 0.0, 0.0, 0.0);
		ALfloat vec1[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
		alListenerfv(AL_ORIENTATION, vec1);

		// set volume
		alListenerf(AL_GAIN, m_volume);
	}
Exemple #2
0
int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
{
	int rc;
	if (!bl || !bl->erase) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	FL_DBG("%s: 0x%" PRIx64 "\t0x%" PRIx64 "\n", __func__, pos, len);

	/* Programmer may be making a horrible mistake without knowing it */
	if (pos & bl->erase_mask) {
		FL_ERR("blocklevel_erase: pos (0x%"PRIx64") is not erase block (0x%08x) aligned\n",
				pos, bl->erase_mask + 1);
		return FLASH_ERR_ERASE_BOUNDARY;
	}

	if (len & bl->erase_mask) {
		FL_ERR("blocklevel_erase: len (0x%"PRIx64") is not erase block (0x%08x) aligned\n",
				len, bl->erase_mask + 1);
		return FLASH_ERR_ERASE_BOUNDARY;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->erase(bl, pos, len);

	release(bl);

	return rc;
}
Exemple #3
0
int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl,
		struct flash_chip **flash_chip)
{
	struct flash_chip *c;
	int rc;

	if (!bl)
		return FLASH_ERR_PARM_ERROR;

	*bl = NULL;

	c = malloc(sizeof(struct flash_chip));
	if (!c)
		return FLASH_ERR_MALLOC_FAILED;
	memset(c, 0, sizeof(*c));
	c->ctrl = ctrl;

	rc = flash_identify(c);
	if (rc) {
		FL_ERR("LIBFLASH: Flash identification failed\n");
		goto bail;
	}
	c->smart_buf = malloc(c->min_erase_mask + 1);
	if (!c->smart_buf) {
		FL_ERR("LIBFLASH: Failed to allocate smart buffer !\n");
		rc = FLASH_ERR_MALLOC_FAILED;
		goto bail;
	}
	rc = flash_configure(c);
	if (rc)
		FL_ERR("LIBFLASH: Flash configuration failed\n");
bail:
	if (rc) {
		free(c);
		return rc;
	}

	/* The flash backend doesn't support reiniting it */
	c->bl.keep_alive = true;
	c->bl.reacquire = NULL;
	c->bl.release = NULL;
	c->bl.read = &flash_read;
	c->bl.write = &flash_smart_write;
	c->bl.erase = &flash_erase;
	c->bl.get_info = &flash_get_info;
	c->bl.erase_mask = c->min_erase_mask;
	c->bl.flags = WRITE_NEED_ERASE;

	*bl = &(c->bl);
	if (flash_chip)
		*flash_chip = c;

	return 0;
}
Exemple #4
0
static int fl_chip_id(struct spi_flash_ctrl *ct, uint8_t *id_buf,
		      uint32_t *id_size)
{
	int rc;
	uint8_t stat;

	/* Check initial status */
	rc = fl_read_stat(ct, &stat);
	if (rc)
		return rc;

	/* If stuck writing, wait for idle */
	if (stat & STAT_WIP) {
		FL_ERR("LIBFLASH: Flash in writing state ! Waiting...\n");
		rc = fl_sync_wait_idle(ct);
		if (rc)
			return rc;
	} else
		FL_DBG("LIBFLASH: Init status: %02x\n", stat);

	/* Fallback to get ID manually */
	rc = ct->cmd_rd(ct, CMD_RDID, false, 0, id_buf, 3);
	if (rc)
		return rc;
	*id_size = 3;

	return 0;
}
Exemple #5
0
int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,
		uint32_t *erase_granule)
{
	int rc;

	if (!bl || !bl->get_info) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->get_info(bl, name, total_size, erase_granule);

	/* Check the validity of what we are being told */
	if (erase_granule && *erase_granule != bl->erase_mask + 1)
		FL_ERR("blocklevel_get_info: WARNING: erase_granule (0x%08x) and erase_mask"
				" (0x%08x) don't match\n", *erase_granule, bl->erase_mask + 1);

	release(bl);

	return rc;
}
Exemple #6
0
/**
 * Copy data from an input buffer with ECC to an output buffer without ECC.
 * Correct it along the way and check for errors.
 *
 * @dst:	destination buffer without ECC
 * @src:	source buffer with ECC
 * @len:	number of bytes of data to copy (without ecc).
                     Must be 8 byte aligned.
 *
 * @return:	eccBitfield or 0-64.
 *
 * @retval GD - Data is good.
 * @retval UE - Data is uncorrectable.
 * @retval all others - which bit was corrected.
 */
uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
{
	beint64_t data;
	uint8_t ecc;
	uint32_t i;
	uint8_t badbit;

	if (len & 0x7) {
		/* TODO: we could probably handle this */
		FL_ERR("ECC data length must be 8 byte aligned length:%i\n",
			len);
		return UE;
	}

	/* Handle in chunks of 8 bytes, so adjust the length */
	len >>= 3;

	for (i = 0; i < len; i++) {
		data = (src + i)->data;
		ecc = (src + i)->ecc;

		badbit = eccverify(be64_to_cpu(data), ecc);
		if (badbit == UE) {
			FL_ERR("ECC: uncorrectable error: %016lx %02x\n",
				(long unsigned int)be64_to_cpu(data), ecc);
			return badbit;
		}
		*dst = data;
		if (badbit <= UE)
			FL_INF("ECC: correctable error: %i\n", badbit);
		if (badbit < 64)
			*dst = (uint64_t)be64_to_cpu(eccflipbit(be64_to_cpu(data), badbit));
		dst++;
	}
	return GD;
}
Exemple #7
0
	void Cell::removeInstance(Instance* instance) {
		if (m_instances.erase(instance) == 0) {
			FL_ERR(_log, "Tried to remove an instance from cell, but given instance could not be found.");
			return;
		}
		CellCache* cache = m_layer->getCellCache();
		if (instance->isVisitor()) {
			uint16_t visitorRadius = instance->getVisitorRadius();
			std::vector<Cell*> cells;
			switch(instance->getVisitorShape()) {
				case ITYPE_QUAD_SHAPE: {
					Rect size(m_coordinate.x-visitorRadius, m_coordinate.y-visitorRadius,
						(visitorRadius*2)+1, (visitorRadius*2)+1);
					cells = cache->getCellsInRect(size);
				}
					break;

				case ITYPE_CIRCLE_SHAPE: {
					cells = cache->getCellsInCircle(m_coordinate, visitorRadius);
				}
					break;

				default: break;
			}
			for (std::vector<Cell*>::iterator it = cells.begin(); it != cells.end(); ++it) {
				(*it)->removeVisitorInstance(instance);
				const std::vector<Instance*>& cv = (*it)->getVisitorInstances();
				if (!cv.empty()) {
					(*it)->setFoWType(CELLV_REVEALED);
				} else {
					(*it)->setFoWType(CELLV_MASKED);
				}
			}
			cache->setFowUpdate(true);
		}
		if (instance->isSpecialCost()) {
			cache->removeCellFromCost(instance->getCostId(), this);
		}
		if (instance->getObject()->getArea() != "") {
			cache->removeCellFromArea(instance->getObject()->getArea(), this);
		}
		callOnInstanceExited(instance);
		updateCellBlockingInfo();
	}
Exemple #8
0
static int flash_set_4b(struct flash_chip *c, bool enable)
{
	struct spi_flash_ctrl *ct = c->ctrl;
	int rc;

	/* Don't have low level interface, assume all is well */
	if (!ct->cmd_wr)
		return 0;

	/* Some flash chips want this */
	rc = fl_wren(ct);
	if (rc) {
		FL_ERR("LIBFLASH: Error %d enabling write for set_4b\n", rc);
		/* Ignore the error & move on (could be wrprotect chip) */
	}

	/* Ignore error in case chip is write protected */
	return ct->cmd_wr(ct, enable ? CMD_EN4B : CMD_EX4B, false, 0, NULL, 0);
}
Exemple #9
0
int ffs_part_info(struct ffs_handle *ffs, uint32_t part_idx,
		  char **name, uint32_t *start,
		  uint32_t *total_size, uint32_t *act_size, bool *ecc)
{
	struct ffs_entry *raw_ent;
	struct ffs_entry ent;
	char *n;
	int rc;

	if (part_idx >= ffs->hdr.entry_count)
		return FFS_ERR_PART_NOT_FOUND;

	raw_ent = ffs_get_part(ffs, part_idx, NULL);
	if (!raw_ent)
		return FFS_ERR_PART_NOT_FOUND;

	rc = ffs_check_convert_entry(&ent, raw_ent);
	if (rc) {
		FL_ERR("FFS: Bad entry %d in partition map\n", part_idx);
		return rc;
	}
	if (start)
		*start = ent.base * ffs->hdr.block_size;
	if (total_size)
		*total_size = ent.size * ffs->hdr.block_size;
	if (act_size)
		*act_size = ent.actual;
	if (ecc)
		*ecc = ((ent.user.datainteg & FFS_ENRY_INTEG_ECC) != 0);

	if (name) {
		n = malloc(PART_NAME_MAX + 1);
		if (!n)
			return FLASH_ERR_MALLOC_FAILED;
		memset(n, 0, PART_NAME_MAX + 1);
		strncpy(n, ent.name, PART_NAME_MAX);
		*name = n;
	}
	return 0;
}
	SoundManager::~SoundManager() {

		// free all soundemitters

		for (std::vector<SoundEmitter*>::iterator it = m_emittervec.begin(), it_end = m_emittervec.end(); it != it_end;  ++it) {
			if ((*it) != NULL) {
				delete (*it);
			}
		}

		m_emittervec.clear();

		if (m_device) {
			alcDestroyContext(m_context);
			alcCloseDevice(m_device);
			m_device = NULL;
		}

		if (alcGetError(NULL) != ALC_NO_ERROR) {
			FL_ERR(_log, LMsg() << "error closing openal device");
		}
	}
Exemple #11
0
/* Exported for internal use */
int fl_wren(struct spi_flash_ctrl *ct)
{
	int i, rc;
	uint8_t stat;

	/* Some flashes need it to be hammered */
	for (i = 0; i < 1000; i++) {
		rc = ct->cmd_wr(ct, CMD_WREN, false, 0, NULL, 0);
		if (rc) return rc;
		rc = fl_read_stat(ct, &stat);
		if (rc) return rc;
		if (stat & STAT_WIP) {
			FL_ERR("LIBFLASH: WREN has WIP status set !\n");
			rc = fl_sync_wait_idle(ct);
			if (rc)
				return rc;
			continue;
		}
		if (stat & STAT_WEN)
			return 0;
	}
	return FLASH_ERR_WREN_TIMEOUT;
}
Exemple #12
0
	bool Layer::addInstance(Instance* instance, const ExactModelCoordinate& p){
        if( !instance ){
            FL_ERR(_log, "Tried to add an instance to layer, but given instance is invalid");
            return false;
        }

	    Location& location = instance->getLocationRef();
		location.setLayer(this);
		location.setExactLayerCoordinates(p);

		m_instances.push_back(instance);
		m_instanceTree->addInstance(instance);
		if(instance->isActive()) {
			setInstanceActivityStatus(instance, instance->isActive());
		}

		std::vector<LayerChangeListener*>::iterator i = m_changeListeners.begin();
		while (i != m_changeListeners.end()) {
			(*i)->onInstanceCreate(this, instance);
			++i;
		}
		m_changed = true;
		return true;
	}
Exemple #13
0
/**
 * Copy data from an input buffer without ECC to an output buffer with ECC.
 *
 * @dst:	destination buffer with ECC
 * @src:	source buffer without ECC
 * @len:	number of bytes of data to copy (without ecc, length of src).
 *       Note: dst must be big enough to hold ecc bytes as well.
                     Must be 8 byte aligned.
 *
 * @return:	eccBitfield.
 *
 * @retval GD - Success.
 * @retval UE - Length is not 8 byte aligned.
 */
uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
{
	struct ecc64 ecc_word;
	uint32_t i;

	if (len & 0x7) {
		/* TODO: we could problably handle this */
		FL_ERR("Data to add ECC bytes to must be 8 byte aligned length: %i\n",
				len);
		return UE;
	}

	/* Handle in chunks of 8 bytes, so adjust the length */
	len >>= 3;

	for (i = 0; i < len; i++) {
		ecc_word.ecc = eccgenerate(be64_to_cpu(*(src + i)));
		ecc_word.data = *(src + i);

		*(dst + i) = ecc_word;
	}

	return GD;
}
Exemple #14
0
int ffs_lookup_part(struct ffs_handle *ffs, const char *name,
		    uint32_t *part_idx)
{
	struct ffs_entry ent;
	uint32_t i;
	int rc;

	/* Lookup the requested partition */
	for (i = 0; i < ffs->hdr.entry_count; i++) {
		struct ffs_entry *src_ent  = ffs_get_part(ffs, i, NULL);
		rc = ffs_check_convert_entry(&ent, src_ent);
		if (rc) {
			FL_ERR("FFS: Bad entry %d in partition map\n", i);
			continue;
		}
		if (!strncmp(name, ent.name, sizeof(ent.name)))
			break;
	}
	if (i >= ffs->hdr.entry_count)
		return FFS_ERR_PART_NOT_FOUND;
	if (part_idx)
		*part_idx = i;
	return 0;
}
    AnimationPtr AnimationLoader::load(const std::string& filename) {
        bfs::path animPath(filename);

        std::string animationFilename = animPath.string();

        TiXmlDocument doc;

        AnimationPtr animation;

        try {
            RawData* data = m_vfs->open(animationFilename);

            if (data) {
                if (data->getDataLength() != 0) {
                    doc.Parse(data->readString(data->getDataLength()).c_str());

                    if (doc.Error()) {
                        return animation;
                    }

                    // done with data delete resource
                    delete data;
                    data = 0;
                }
            }
        }
        catch (NotFound& e) {
            FL_ERR(_log, e.what());

            // TODO - should we abort here
            //        or rethrow the exception
            //        or just keep going

            return animation;
        }

        // if we get here then everything loaded properly
        // so we can just parse out the contents
        TiXmlElement* root = doc.RootElement();

        if (root) {
            animation.reset(new Animation());

            int animDelay = 0;
            root->QueryValueAttribute("delay", &animDelay);

            int animXoffset = 0;
            int animYoffset = 0;
            int action = -1;
            root->QueryValueAttribute("x_offset", &animXoffset);
            root->QueryValueAttribute("y_offset", &animYoffset);
            root->QueryValueAttribute("action", &action);

            for (TiXmlElement* frameElement = root->FirstChildElement("frame"); frameElement; frameElement = frameElement->NextSiblingElement("frame")) {
                if (animation) {
                    animation->setActionFrame(action);

                    const std::string* sourceId = frameElement->Attribute(std::string("source"));

                    if (sourceId) {
                        bfs::path framePath(filename);

                        if (HasParentPath(framePath)) {
							framePath = GetParentPath(framePath) / *sourceId;
						} else {
							framePath = bfs::path(*sourceId);
						}

						ImagePtr imagePtr;
						if(!m_imageManager->exists(framePath.string())) {
                        	imagePtr = m_imageManager->create(framePath.string());
						}
						else {
							imagePtr = m_imageManager->getPtr(framePath.string());
						}

                        if (imagePtr) {
                            int frameXoffset = 0;
                            int frameYoffset = 0;

                            int success = root->QueryValueAttribute("x_offset", &frameXoffset);

                            if (success == TIXML_SUCCESS) {
                                imagePtr->setXShift(frameXoffset);
                            }
                            else {
                                imagePtr->setXShift(animXoffset);
                            }

                            success = root->QueryValueAttribute("y_offset", &frameYoffset);

                            if (success == TIXML_SUCCESS) {
                                imagePtr->setYShift(frameYoffset);
                            }
                            else {
                                imagePtr->setYShift(animYoffset);
                            }

                            int frameDelay = 0;
                            success = root->QueryValueAttribute("delay", &frameDelay);

                            if (success == TIXML_SUCCESS) {
                                animation->addFrame(imagePtr, frameDelay);
                            }
                            else {
                                animation->addFrame(imagePtr, animDelay);
                            }
                        }
                    }
                }
            }
        }

        return animation;
    }
Exemple #16
0
int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf,
		uint64_t len)
{
	int rc, ecc_protection;
	struct ecc64 *buffer;
	uint64_t ecc_len;
	uint64_t ecc_start, ecc_pos, ecc_diff;

	FL_DBG("%s: 0x%" PRIx64 "\t%p\t0x%" PRIx64 "\n", __func__, pos, buf, len);
	if (!bl || !buf) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	ecc_protection = ecc_protected(bl, pos, len, &ecc_start);

	FL_DBG("%s: 0x%" PRIx64 " for 0x%" PRIx64 " ecc=%s\n",
		__func__, pos, len, ecc_protection ?
		(ecc_protection == -1 ? "partial" : "yes") : "no");

	if (!ecc_protection)
		return blocklevel_raw_write(bl, pos, buf, len);

	/*
	 * The region we're writing to has both ecc protection and not.
	 * Perhaps one day in the future blocklevel can cope with this.
	 */
	if (ecc_protection == -1) {
		FL_ERR("%s: Can't cope with partial ecc\n", __func__);
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	pos = with_ecc_pos(ecc_start, pos);

	ecc_pos = ecc_buffer_align(ecc_start, pos);
	ecc_diff = pos - ecc_pos;
	ecc_len = ecc_buffer_size(len + ecc_diff);

	FL_DBG("%s: adjusted_pos: 0x%" PRIx64 ", ecc_pos: 0x%" PRIx64
			", ecc_diff: 0x%" PRIx64 ", ecc_len: 0x%" PRIx64 "\n",
			__func__, pos, ecc_pos, ecc_diff, ecc_len);

	buffer = malloc(ecc_len);
	if (!buffer) {
		errno = ENOMEM;
		rc = FLASH_ERR_MALLOC_FAILED;
		goto out;
	}

	if (ecc_diff) {
		uint64_t start_chunk = ecc_diff;
		uint64_t end_chunk = BYTES_PER_ECC - ecc_diff;
		uint64_t end_len = ecc_len - end_chunk;

		/*
		 * Read the start bytes that memcpy_to_ecc_unaligned() will need
		 * to calculate the first ecc byte
		 */
		rc = blocklevel_raw_read(bl, ecc_pos, buffer, start_chunk);
		if (rc) {
			errno = EBADF;
			rc = FLASH_ERR_ECC_INVALID;
			goto out;
		}

		/*
		 * Read the end bytes that memcpy_to_ecc_unaligned() will need
		 * to calculate the last ecc byte
		 */
		rc = blocklevel_raw_read(bl, ecc_pos + end_len, ((char *)buffer) + end_len,
				end_chunk);
		if (rc) {
			errno = EBADF;
			rc = FLASH_ERR_ECC_INVALID;
			goto out;
		}

		if (memcpy_to_ecc_unaligned(buffer, buf, len, ecc_diff)) {
			errno = EBADF;
			rc = FLASH_ERR_ECC_INVALID;
			goto out;
		}
	} else {
		if (memcpy_to_ecc(buffer, buf, len)) {
			errno = EBADF;
			rc = FLASH_ERR_ECC_INVALID;
			goto out;
		}
	}
	rc = blocklevel_raw_write(bl, pos, buffer, ecc_len);

out:
	free(buffer);
	return rc;
}
Exemple #17
0
int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
{
	int rc, ecc_protection;
	struct ecc64 *buffer;
	uint64_t ecc_pos, ecc_start, ecc_diff, ecc_len;

	FL_DBG("%s: 0x%" PRIx64 "\t%p\t0x%" PRIx64 "\n", __func__, pos, buf, len);
	if (!bl || !buf) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	ecc_protection = ecc_protected(bl, pos, len, &ecc_start);

	FL_DBG("%s: 0x%" PRIx64 " for 0x%" PRIx64 " ecc=%s\n",
		__func__, pos, len, ecc_protection ?
		(ecc_protection == -1 ? "partial" : "yes") : "no");

	if (!ecc_protection)
		return blocklevel_raw_read(bl, pos, buf, len);

	/*
	 * The region we're reading to has both ecc protection and not.
	 * Perhaps one day in the future blocklevel can cope with this.
	 */
	if (ecc_protection == -1) {
		FL_ERR("%s: Can't cope with partial ecc\n", __func__);
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	pos = with_ecc_pos(ecc_start, pos);

	ecc_pos = ecc_buffer_align(ecc_start, pos);
	ecc_diff = pos - ecc_pos;
	ecc_len = ecc_buffer_size(len + ecc_diff);

	FL_DBG("%s: adjusted_pos: 0x%" PRIx64 ", ecc_pos: 0x%" PRIx64
			", ecc_diff: 0x%" PRIx64 ", ecc_len: 0x%" PRIx64 "\n",
			__func__, pos, ecc_pos, ecc_diff, ecc_len);
	buffer = malloc(ecc_len);
	if (!buffer) {
		errno = ENOMEM;
		rc = FLASH_ERR_MALLOC_FAILED;
		goto out;
	}

	rc = blocklevel_raw_read(bl, ecc_pos, buffer, ecc_len);
	if (rc)
		goto out;

	/*
	 * Could optimise and simply call memcpy_from_ecc() if ecc_diff
	 * == 0 but _unaligned checks and bascially does that for us
	 */
	if (memcpy_from_ecc_unaligned(buf, buffer, len, ecc_diff)) {
		errno = EBADF;
		rc = FLASH_ERR_ECC_INVALID;
	}

out:
	free(buffer);
	return rc;
}
Exemple #18
0
static int flash_write(struct blocklevel_device *bl, uint32_t dst, const void *src,
		uint32_t size, bool verify)
{
	struct flash_chip *c = container_of(bl, struct flash_chip, bl);
	struct spi_flash_ctrl *ct = c->ctrl;
	uint32_t todo = size;
	uint32_t d = dst;
	const void *s = src;
	uint8_t vbuf[0x100];
	int rc;	

	/* Some sanity checking */
	if (((dst + size) <= dst) || !size || (dst + size) > c->tsize)
		return FLASH_ERR_PARM_ERROR;

	FL_DBG("LIBFLASH: Writing to 0x%08x..0%08x...\n", dst, dst + size);

	/*
	 * If the controller supports write and either we are in 3b mode
	 * or we are in 4b *and* the controller supports it, then do a
	 * high level write.
	 */
	if ((!c->mode_4b || ct->set_4b) && ct->write) {
		rc = ct->write(ct, dst, src, size);
		if (rc)
			return rc;
		goto writing_done;
	}

	/* Otherwise, go manual if supported */
	if (!ct->cmd_wr)
		return FLASH_ERR_CTRL_CMD_UNSUPPORTED;

	/* Iterate for each page to write */
	while(todo) {
		uint32_t chunk;

		/* Handle misaligned start */
		chunk = 0x100 - (d & 0xff);
		if (chunk > todo)
			chunk = todo;

		rc = fl_wpage(c, d, s, chunk);
		if (rc) return rc;
		d += chunk;
		s += chunk;
		todo -= chunk;
	}

 writing_done:
	if (!verify)
		return 0;

	/* Verify */
	FL_DBG("LIBFLASH: Verifying...\n");

	while(size) {
		uint32_t chunk;

		chunk = sizeof(vbuf);
		if (chunk > size)
			chunk = size;
		rc = flash_read(bl, dst, vbuf, chunk);
		if (rc) return rc;
		if (memcmp(vbuf, src, chunk)) {
			FL_ERR("LIBFLASH: Miscompare at 0x%08x\n", dst);
			return FLASH_ERR_VERIFY_FAILURE;
		}
		dst += chunk;
		src += chunk;
		size -= chunk;
	}
	return 0;
}
Exemple #19
0
static int flash_identify(struct flash_chip *c)
{
	struct spi_flash_ctrl *ct = c->ctrl;
	const struct flash_info *info = NULL;
	uint32_t iid, id_size;
#define MAX_ID_SIZE	16
	uint8_t id[MAX_ID_SIZE];
	int rc, i;

	if (ct->chip_id) {
		/* High level controller interface */
		id_size = MAX_ID_SIZE;
		rc = ct->chip_id(ct, id, &id_size);
	} else
		rc = fl_chip_id(ct, id, &id_size);
	if (rc)
		return rc;
	if (id_size < 3)
		return FLASH_ERR_CHIP_UNKNOWN;

	/* Convert to a dword for lookup */
	iid = id[0];
	iid = (iid << 8) | id[1];
	iid = (iid << 8) | id[2];

	FL_DBG("LIBFLASH: Flash ID: %02x.%02x.%02x (%06x)\n",
	       id[0], id[1], id[2], iid);

	/* Lookup in flash_info */
	for (i = 0; i < ARRAY_SIZE(flash_info); i++) {
		info = &flash_info[i];
		if (info->id == iid)
			break;		
	}
	if (!info || info->id != iid)
		return FLASH_ERR_CHIP_UNKNOWN;

	c->info = *info;
	c->tsize = info->size;
	ct->finfo = &c->info;

	/*
	 * Let controller know about our settings and possibly
	 * override them
	 */
	if (ct->setup) {
		rc = ct->setup(ct, &c->tsize);
		if (rc)
			return rc;
	}

	/* Calculate min erase granularity */
	if (c->info.flags & FL_ERASE_4K)
		c->min_erase_mask = 0xfff;
	else if (c->info.flags & FL_ERASE_32K)
		c->min_erase_mask = 0x7fff;
	else if (c->info.flags & FL_ERASE_64K)
		c->min_erase_mask = 0xffff;
	else {
		/* No erase size ? oops ... */
		FL_ERR("LIBFLASH: No erase sizes !\n");
		return FLASH_ERR_CTRL_CONFIG_MISMATCH;
	}

	FL_DBG("LIBFLASH: Found chip %s size %dM erase granule: %dK\n",
	       c->info.name, c->tsize >> 20, (c->min_erase_mask + 1) >> 10);

	return 0;
}
Exemple #20
0
int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
		struct ffs_handle **ffs, bool mark_ecc)
{
	struct ffs_hdr hdr;
	struct ffs_hdr blank_hdr;
	struct ffs_handle *f;
	uint64_t total_size;
	int rc, i;

	if (!ffs || !bl)
		return FLASH_ERR_PARM_ERROR;
	*ffs = NULL;

	rc = blocklevel_get_info(bl, NULL, &total_size, NULL);
	if (rc) {
		FL_ERR("FFS: Error %d retrieving flash info\n", rc);
		return rc;
	}
	if (total_size > UINT_MAX)
		return FLASH_ERR_VERIFY_FAILURE;
	if ((offset + max_size) < offset)
		return FLASH_ERR_PARM_ERROR;

	if ((max_size > total_size))
		return FLASH_ERR_PARM_ERROR;

	/* Read flash header */
	rc = blocklevel_read(bl, offset, &hdr, sizeof(hdr));
	if (rc) {
		FL_ERR("FFS: Error %d reading flash header\n", rc);
		return rc;
	}

	/*
	 * Flash controllers can get deconfigured or otherwise upset, when this
	 * happens they return all 0xFF bytes.
	 * An ffs_hdr consisting of all 0xFF cannot be valid and it would be
	 * nice to drop a hint to the user to help with debugging. This will
	 * help quickly differentiate between flash corruption and standard
	 * type 'reading from the wrong place' errors vs controller errors or
	 * reading erased data.
	 */
	memset(&blank_hdr, UINT_MAX, sizeof(struct ffs_hdr));
	if (memcmp(&blank_hdr, &hdr, sizeof(struct ffs_hdr)) == 0) {
		FL_ERR("FFS: Reading the flash has returned all 0xFF.\n");
		FL_ERR("Are you reading erased flash?\n");
		FL_ERR("Is something else using the flash controller?\n");
		return FLASH_ERR_BAD_READ;
	}

	/* Allocate ffs_handle structure and start populating */
	f = malloc(sizeof(*f));
	if (!f)
		return FLASH_ERR_MALLOC_FAILED;
	memset(f, 0, sizeof(*f));

	f->toc_offset = offset;
	f->max_size = max_size;
	f->bl = bl;

	/* Convert and check flash header */
	rc = ffs_check_convert_header(&f->hdr, &hdr);
	if (rc) {
		FL_INF("FFS: Flash header not found. Code: %d\n", rc);
		goto out;
	}

	/* Check header is sane */
	if ((f->hdr.block_size * f->hdr.size) > max_size) {
		rc = FLASH_ERR_PARM_ERROR;
		FL_ERR("FFS: Flash header exceeds max flash size\n");
		goto out;
	}

	if ((f->hdr.entry_size * f->hdr.entry_count) >
			(f->hdr.block_size * f->hdr.size)) {
		rc = FLASH_ERR_PARM_ERROR;
		FL_ERR("FFS: Flash header entries exceeds available blocks\n");
		goto out;
	}

	/*
	 * Decide how much of the image to grab to get the whole
	 * partition map.
	 */
	f->cached_size = f->hdr.block_size * f->hdr.size;
	/* Check for overflow or a silly size */
	if (!f->hdr.size || f->cached_size / f->hdr.size != f->hdr.block_size) {
		rc= FLASH_ERR_MALLOC_FAILED;
		FL_ERR("FFS: Cache size overflow (0x%x * 0x%x)\n",
				f->hdr.block_size, f->hdr.size);
		goto out;
	}

	FL_DBG("FFS: Partition map size: 0x%x\n", f->cached_size);

	/* Allocate cache */
	f->cache = malloc(f->cached_size);
	if (!f->cache) {
		rc = FLASH_ERR_MALLOC_FAILED;
		goto out;
	}

	/* Read the cached map */
	rc = blocklevel_read(bl, offset, f->cache, f->cached_size);
	if (rc) {
		FL_ERR("FFS: Error %d reading flash partition map\n", rc);
		goto out;
	}

	if (mark_ecc) {
		uint32_t start, total_size;
		bool ecc;
		for (i = 0; i < f->hdr.entry_count; i++) {
			rc = ffs_part_info(f, i, NULL, &start, &total_size,
					NULL, &ecc);
			if (rc) {
				FL_ERR("FFS: Failed to read ffs partition %d\n",
						i);
				goto out;
			}
			if (ecc) {
				rc = blocklevel_ecc_protect(bl, start, total_size);
				if (rc) {
					FL_ERR("FFS: Failed to blocklevel_ecc_protect(0x%08x, 0x%08x)\n",
					       start, total_size);
					goto out;
				}
			}  /* ecc */
		} /* for */
	}

out:
	if (rc == 0)
		*ffs = f;
	else
		free(f);

	return rc;
}
Exemple #21
0
static int flash_configure(struct flash_chip *c)
{
	struct spi_flash_ctrl *ct = c->ctrl;
	int rc;

	/* Crop flash size if necessary */
	if (c->tsize > 0x01000000 && !(c->info.flags & FL_CAN_4B)) {
		FL_ERR("LIBFLASH: Flash chip cropped to 16M, no 4b mode\n");
		c->tsize = 0x01000000;
	}

	/* If flash chip > 16M, enable 4b mode */
	if (c->tsize > 0x01000000) {
		FL_DBG("LIBFLASH: Flash >16MB, enabling 4B mode...\n");

		/* Set flash to 4b mode if we can */
		if (ct->cmd_wr) {
			rc = flash_set_4b(c, true);
			if (rc) {
				FL_ERR("LIBFLASH: Failed to set flash 4b mode\n");
				return rc;
			}
		}


		/* Set controller to 4b mode if supported */
		if (ct->set_4b) {
			FL_DBG("LIBFLASH: Enabling controller 4B mode...\n");
			rc = ct->set_4b(ct, true);
			if (rc) {
				FL_ERR("LIBFLASH: Failed to set controller 4b mode\n");
				return rc;
			}
		}
	} else {
		FL_DBG("LIBFLASH: Flash <=16MB, disabling 4B mode...\n");

		/*
		 * If flash chip supports 4b mode, make sure we disable
		 * it in case it was left over by the previous user
		 */
		if (c->info.flags & FL_CAN_4B) {
			rc = flash_set_4b(c, false);
			if (rc) {
				FL_ERR("LIBFLASH: Failed to"
				       " clear flash 4b mode\n");
				return rc;
			}
		}
		/* Set controller to 3b mode if mode switch is supported */
		if (ct->set_4b) {
			FL_DBG("LIBFLASH: Disabling controller 4B mode...\n");
			rc = ct->set_4b(ct, false);
			if (rc) {
				FL_ERR("LIBFLASH: Failed to"
				       " clear controller 4b mode\n");
				return rc;
			}
		}
	}
	return 0;
}