Beispiel #1
0
static int flash_erase(struct blocklevel_device *bl, uint64_t dst, uint64_t size)
{
	struct flash_chip *c = container_of(bl, struct flash_chip, bl);
	struct spi_flash_ctrl *ct = c->ctrl;
	uint32_t chunk;
	uint8_t cmd;
	int rc;

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

	/* Check boundaries fit erase blocks */
	if ((dst | size) & c->min_erase_mask)
		return FLASH_ERR_ERASE_BOUNDARY;

	FL_DBG("LIBFLASH: Erasing 0x%" PRIx64"..0%" PRIx64 "...\n",
	       dst, dst + size);

	/* Use controller erase if supported */
	if (ct->erase)
		return ct->erase(ct, dst, size);

	/* Allright, loop as long as there's something to erase */
	while(size) {
		/* How big can we make it based on alignent & size */
		fl_get_best_erase(c, dst, size, &chunk, &cmd);

		/* Poke write enable */
		rc = fl_wren(ct);
		if (rc)
			return rc;

		/* Send erase command */
		rc = ct->cmd_wr(ct, cmd, true, dst, NULL, 0);
		if (rc)
			return rc;

		/* Wait for write complete */
		rc = fl_sync_wait_idle(ct);
		if (rc)
			return rc;

		size -= chunk;
		dst += chunk;
	}
	return 0;
}
Beispiel #2
0
	ModelCoordinate HexGrid::toLayerCoordinates(const ExactModelCoordinate& map_coord) {
		FL_DBG(_log, LMsg("==============\nConverting map coords ") << map_coord << " to int32_t layer coords...");
		ExactModelCoordinate elc = m_inverse_matrix * map_coord;
		elc.y *= VERTICAL_MULTIP_INV;

		// approximate conversion using squares instead of hexes
		if( static_cast<int32_t>(round(elc.y)) & 1 )
			elc.x -= 0.5;
		ExactModelCoordinate lc = ExactModelCoordinate(round(elc.x), round(elc.y), round(elc.z));

		int32_t x = static_cast<int32_t>(lc.x);
		int32_t y = static_cast<int32_t>(lc.y);
		int32_t z = static_cast<int32_t>(lc.z);

		// distance of given point from our approximation
		// If y uneven dx=-dx and dy=-dy
		double dx,dy;
		if (y & 1) {
			dx = elc.x - lc.x;
			dy = elc.y - lc.y;
		} else {
			dx = lc.x - elc.x;
			dy = lc.y - elc.y;
		}

		// adjustment for cases where our approximation lies beyond the hex edge
		if (ABS(dy) > ((HEX_TO_CORNER - HEX_EDGE_GRADIENT * ABS(dx)) * VERTICAL_MULTIP_INV)) {
			int8_t ddx, ddy;
			if (dx>0) ddx = -1;
			else ddx = 0;

			if (dy>0) ddy = -1;
			else ddy = 1;

			if (y & 1) {
				ddx = -ddx;
				ddy = -ddy;
			}

			x += ddx;
			y += ddy;
		}

		return ModelCoordinate(x,y,z);
	}
Beispiel #3
0
	void ImageManager::removeUnreferenced() {
		ImageHandleMapIterator it = m_imgHandleMap.begin(),
			itend = m_imgHandleMap.end();

		std::vector<int> imgHandles;

		int32_t count = 0;
		for ( ; it != itend; ++it) {
			if ( it->second.useCount() == 2) {
				imgHandles.push_back(it->second->getHandle());
				count++;
			}
		}

		for (std::vector<int>::iterator it = imgHandles.begin(); it != imgHandles.end(); ++it) {
			remove(*it);
		}

		FL_DBG(_log, LMsg("ImageManager::removeUnreferenced() - ") << "Removed " << count << " unreferenced resources.");
	}
Beispiel #4
0
int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
{
	int rc;

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

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

	rc = bl->read(bl, pos, buf, len);

	release(bl);

	return rc;
}
Beispiel #5
0
    void Consequent::modify(scalar activationDegree, const TNorm* implication) {
        if (not isLoaded()) {
            throw fl::Exception("[consequent error] consequent <" + getText() + "> is not loaded", FL_AT);
        }
        for (std::size_t i = 0; i < _conclusions.size(); ++i) {
            Proposition* proposition = _conclusions.at(i);
            if (proposition->variable->isEnabled()) {
                if (not proposition->hedges.empty()) {
                    for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin();
                            rit != proposition->hedges.rend(); ++rit) {
                        activationDegree = (*rit)->hedge(activationDegree);
                    }
                }

                OutputVariable * outputVariable = static_cast<OutputVariable*> (proposition->variable);
                Activated term(proposition->term, activationDegree, implication);
                outputVariable->fuzzyOutput()->addTerm(term);
                FL_DBG("Aggregating " << term.toString());
            }
        }
    }
Beispiel #6
0
    scalar SmallestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
        if (not fl::Op::isFinite(minimum + maximum)) {
            return fl::nan;
        }
        if (maximum - minimum > _resolution) {
            FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
                    "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
                    "improve the accuracy, the resolution should be at least equal to the range.");
        }
        scalar dx = (maximum - minimum) / _resolution;
        scalar x, y;
        scalar ymax = -1.0, xsmallest = minimum;
        for (int i = 0; i < _resolution; ++i) {
            x = minimum + (i + 0.5) * dx;
            y = term->membership(x);

            if (Op::isGt(y, ymax)) {
                xsmallest = x;
                ymax = y;
            }
        }
        return xsmallest;
    }
Beispiel #7
0
    scalar WeightedAverage::defuzzify(const Term* term,
            scalar minimum, scalar maximum) const {
        (void) minimum;
        (void) maximum;
        const Accumulated* takagiSugeno = dynamic_cast<const Accumulated*> (term);
        if (not takagiSugeno) {
            std::ostringstream ss;
            ss << "[defuzzification error]"
                    << "expected an Accumulated term instead of"
                    << "<" << term->toString() << ">";
            throw fl::Exception(ss.str(), FL_AT);
        }

        scalar sum = 0.0;
        scalar weights = 0.0;
        FL_DBG("Defuzzifying " << takagiSugeno->numberOfTerms() << " output terms");
        for (int i = 0; i < takagiSugeno->numberOfTerms(); ++i) {
            const Thresholded* thresholded = dynamic_cast<const Thresholded*> (takagiSugeno->getTerm(i));
            if (not thresholded) {
                std::ostringstream ss;
                ss << "[defuzzification error]"
                        << "expected a Thresholded term instead of"
                        << "<" << takagiSugeno->getTerm(i)->toString() << ">";
                throw fl::Exception(ss.str(), FL_AT);
            }

            scalar w = thresholded->getThreshold();
            scalar z = Tsukamoto::tsukamoto(thresholded,
                    takagiSugeno->getMinimum(), takagiSugeno->getMaximum());
            //Traditionally, activation is the AlgebraicProduct
            sum += thresholded->getActivation()->compute(w, z);
            weights += w;
        }

        return sum / weights;
    }
Beispiel #8
0
	SubImageFont::SubImageFont(const std::string& filename, const std::string& glyphs)
		: ImageFontBase() {

		FL_LOG(_log, LMsg("guichan_image_font, loading ") << filename << " glyphs " << glyphs);

//prock - 504
		ImagePtr img = ImageManager::instance()->load(filename);
		int32_t image_id = img->getHandle();
		SDL_Surface* surface = img->getSurface();
		m_colorkey = RenderBackend::instance()->getColorKey();

		if( !surface ) {
			throw CannotOpenFile(filename);
		}

		// Make sure we get 32bit RGB
		// and copy the Pixelbuffers surface
		SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
			surface->w,surface->h,32,
			RMASK, GMASK, BMASK ,NULLMASK);

		SDL_BlitSurface(surface,0,tmp,0);
		surface = tmp;

		// Prepare the data for extracting the glyphs.
		uint32_t *pixels = reinterpret_cast<uint32_t*>(surface->pixels);

		int32_t x, w;
		x = 0; w=0;

		SDL_Rect src;

		src.h = surface->h;
		src.y = 0;
		
		uint32_t separator = pixels[0];
		uint32_t colorkey = SDL_MapRGB(surface->format, m_colorkey.r, m_colorkey.g, m_colorkey.b);

		// if colorkey feature is not enabled then manually find the color key in the font
		if (!RenderBackend::instance()->isColorKeyEnabled()) {
			while(x < surface->w && pixels[x] == separator) {
				++x;
			}
			
			colorkey = pixels[x];
		}
		
		// Disable alpha blending, so that we use color keying
		SDL_SetAlpha(surface,0,255);
		SDL_SetColorKey(surface,SDL_SRCCOLORKEY,colorkey);

		FL_DBG(_log, LMsg("image_font")
			<< " glyph separator is " 
			<< pprint(reinterpret_cast<void*>(separator))
			<< " transparent color is " 
			<< pprint(reinterpret_cast<void*>(colorkey)));

		// Finally extract all glyphs
		std::string::const_iterator text_it = glyphs.begin();
		while(text_it != glyphs.end()) {
			w=0;
			while(x < surface->w && pixels[x] == separator)
				++x;
			if( x == surface->w )
				break;

			while(x + w < surface->w && pixels[x + w] != separator)
				++w;

			src.x = x;
			src.w = w;

			tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
					w,surface->h,32,
					RMASK, GMASK, BMASK ,NULLMASK);

			SDL_FillRect(tmp,0,colorkey);
			SDL_BlitSurface(surface,&src,tmp,0);

			// Disable alpha blending, so that we use colorkeying
			SDL_SetAlpha(tmp,0,255);
			SDL_SetColorKey(tmp,SDL_SRCCOLORKEY,colorkey);


			uint32_t codepoint = utf8::next(text_it, glyphs.end());
			m_glyphs[ codepoint ].surface = tmp;

			x += w;
		}

		// Set placeholder glyph
		// This should actually work ith utf8.
		if( m_glyphs.find('?') != m_glyphs.end() ) {
			m_placeholder = m_glyphs['?'];
		} else {
			m_placeholder.surface = 0;
		}

		mHeight = surface->h;
		SDL_FreeSurface(surface);
	}
Beispiel #9
0
    void Antecedent::load(const std::string& antecedent, fl::Rule* rule, const Engine* engine) {
        FL_DBG("Antecedent: " << antecedent);
        unload();
        this->_text = antecedent;
        if (fl::Op::trim(antecedent).empty()) {
            throw fl::Exception("[syntax error] antecedent is empty", FL_AT);
        }
        /*
         Builds an proposition tree from the antecedent of a fuzzy rule.
         The rules are:
         1) After a variable comes 'is',
         2) After 'is' comes a hedge or a term
         3) After a hedge comes a hedge or a term
         4) After a term comes a variable or an operator
         */

        Function function;

        std::string postfix = function.toPostfix(antecedent);
        FL_DBG("Postfix: " << postfix);
        std::stringstream tokenizer(postfix);
        std::string token;

        enum FSM {
            S_VARIABLE = 1, S_IS = 2, S_HEDGE = 4, S_TERM = 8, S_AND_OR = 16
        };
        int state = S_VARIABLE;
        std::stack<Expression*> expressionStack;
        Proposition* proposition = fl::null;
        try {
            while (tokenizer >> token) {
                if (state bitand S_VARIABLE) {
                    Variable* variable = fl::null;
                    if (engine->hasInputVariable(token)) variable = engine->getInputVariable(token);
                    else if (engine->hasOutputVariable(token)) variable = engine->getOutputVariable(token);
                    if (variable) {
                        proposition = new Proposition;
                        proposition->variable = variable;
                        expressionStack.push(proposition);

                        state = S_IS;
                        FL_DBG("Token <" << token << "> is variable");
                        continue;
                    }
                }

                if (state bitand S_IS) {
                    if (token == Rule::isKeyword()) {
                        state = S_HEDGE bitor S_TERM;
                        FL_DBG("Token <" << token << "> is keyword");
                        continue;
                    }
                }

                if (state bitand S_HEDGE) {
                    Hedge* hedge = rule->getHedge(token);
                    if (not hedge) {
                        HedgeFactory* factory = FactoryManager::instance()->hedge();
                        if (factory->hasConstructor(token)) {
                            hedge = factory->constructObject(token);
                            rule->addHedge(hedge);
                        }
                    }
                    if (hedge) {
                        proposition->hedges.push_back(hedge);
                        if (dynamic_cast<Any*> (hedge)) {
                            state = S_VARIABLE bitor S_AND_OR;
                        } else {
                            state = S_HEDGE bitor S_TERM;
                        }
                        FL_DBG("Token <" << token << "> is hedge");
                        continue;
                    }
                }

                if (state bitand S_TERM) {
                    if (proposition->variable->hasTerm(token)) {
                        proposition->term = proposition->variable->getTerm(token);
                        state = S_VARIABLE bitor S_AND_OR;
                        FL_DBG("Token <" << token << "> is term");
                        continue;
                    }
                }

                if (state bitand S_AND_OR) {
                    if (token == Rule::andKeyword() or token == Rule::orKeyword()) {
                        if (expressionStack.size() < 2) {
                            std::ostringstream ex;
                            ex << "[syntax error] logical operator <" << token << "> expects two operands,"
                                    << "but found <" << expressionStack.size() << "> in antecedent";
                            throw fl::Exception(ex.str(), FL_AT);
                        }
                        Operator* fuzzyOperator = new Operator;
                        fuzzyOperator->name = token;
                        fuzzyOperator->right = expressionStack.top();
                        expressionStack.pop();
                        fuzzyOperator->left = expressionStack.top();
                        expressionStack.pop();
                        expressionStack.push(fuzzyOperator);

                        state = S_VARIABLE bitor S_AND_OR;
                        FL_DBG("Subtree: " << fuzzyOperator->toString() <<
                                "(" << fuzzyOperator->left->toString() << ") " <<
                                "(" << fuzzyOperator->right->toString() << ")");
                        continue;
                    }
                }

                //If reached this point, there was an error
                if ((state bitand S_VARIABLE) or (state bitand S_AND_OR)) {
                    std::ostringstream ex;
                    ex << "[syntax error] antecedent expected variable or logical operator, but found <" << token << ">";
                    throw fl::Exception(ex.str(), FL_AT);
                }
                if (state bitand S_IS) {
                    std::ostringstream ex;
                    ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << ">, but found <" << token << ">";
                    throw fl::Exception(ex.str(), FL_AT);
                }
                if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
                    std::ostringstream ex;
                    ex << "[syntax error] antecedent expected hedge or term, but found <" << token << ">";
                    throw fl::Exception(ex.str(), FL_AT);
                }
                std::ostringstream ex;
                ex << "[syntax error] unexpected token <" << token << "> in antecedent";
                throw fl::Exception(ex.str(), FL_AT);
            }

            if (not ((state bitand S_VARIABLE) or (state bitand S_AND_OR))) { //only acceptable final state
                if (state bitand S_IS) {
                    std::ostringstream ex;
                    ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << "> after <" << token << ">";
                    throw fl::Exception(ex.str(), FL_AT);
                }
                if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
                    std::ostringstream ex;
                    ex << "[syntax error] antecedent expected hedge or term after <" << token << ">";
                    throw fl::Exception(ex.str(), FL_AT);
                }
            }

            if (expressionStack.size() != 1) {
                std::vector<std::string> errors;
                while (expressionStack.size() > 1) {
                    Expression* expression = expressionStack.top();
                    expressionStack.pop();
                    errors.push_back(expression->toString());
                    delete expression;
                }
                std::ostringstream ex;
                ex << "[syntax error] unable to parse the following expressions in antecedent <"
                        << Op::join(errors, " ") << ">";
                throw fl::Exception(ex.str(), FL_AT);
            }
        } catch (...) {
            for (std::size_t i = 0; i < expressionStack.size(); ++i) {
                delete expressionStack.top();
                expressionStack.pop();
            }
            throw;
        }
        this->_expression = expressionStack.top();
    }
Beispiel #10
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;
}
	ModelCoordinate HexGrid::toLayerCoordinates(const ExactModelCoordinate& map_coord) {
		FL_DBG(_log, LMsg("==============\nConverting map coords ") << map_coord << " to int layer coords...");
		ExactModelCoordinate elc = m_inverse_matrix * map_coord;
		elc.y *= VERTICAL_MULTIP_INV;
		ExactModelCoordinate lc = ExactModelCoordinate(floor(elc.x), floor(elc.y));
		double dx = elc.x - lc.x;
		double dy = elc.y - lc.y;
		int x = static_cast<int>(lc.x);
		int y = static_cast<int>(lc.y);
		FL_DBG(_log, LMsg("elc=") << elc << ", lc=" << lc);
		FL_DBG(_log, LMsg("x=") << x << ", y=" << y << ", dx=" << dx << ", dy=" << dy);
		ModelCoordinate result;

		if ((y % 2) == 0) {
			FL_DBG(_log, "In even row");
			if ((1 - dy) < HEX_EDGE_HALF) {
				FL_DBG(_log, "In lower rect area");
				result = ModelCoordinate(x, y+1);
			}
			else if (dy < HEX_EDGE_HALF) {
				FL_DBG(_log, "In upper rect area");
				if (dx > 0.5) {
					FL_DBG(_log, "...on right");
					result = ModelCoordinate(x+1, y);
				}
				else {
					FL_DBG(_log, "...on left");
					result = ModelCoordinate(x, y);
				}
			}
			// in middle triangle area
			else {
				FL_DBG(_log, "In middle triangle area");
				if (dx < 0.5) {
					FL_DBG(_log, "In left triangles");
					if (ptInTriangle(ExactModelCoordinate(dx, dy),
					                 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
					                 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
					                 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
					                 )) {
						FL_DBG(_log, "..upper part");
						result = ModelCoordinate(x, y);
					} else {
						FL_DBG(_log, "..lower part");
						result = ModelCoordinate(x, y+1);
					}
				} else {
					FL_DBG(_log, "In right triangles");
					if (ptInTriangle(ExactModelCoordinate(dx, dy),
					                 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
					                 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
					                 ExactModelCoordinate(0.5, VERTICAL_MULTIP * HEX_EDGE_HALF)
					                 )) {
						FL_DBG(_log, "..upper part");
						result = ModelCoordinate(x+1, y);
					} else {
						FL_DBG(_log, "..lower part");
						result = ModelCoordinate(x, y+1);
					}
				}
			}
		}
		else {
			FL_DBG(_log, "In uneven row");
			if (dy < HEX_EDGE_HALF) {
				FL_DBG(_log, "In upper rect area");
				result = ModelCoordinate(x, y);
			}
			else if ((1 - dy) < HEX_EDGE_HALF) {
				FL_DBG(_log, "In lower rect area");
				if (dx > 0.5) {
					FL_DBG(_log, "...on right");
					result = ModelCoordinate(x+1, y+1);
				}
				else {
					FL_DBG(_log, "...on left");
					result = ModelCoordinate(x, y+1);
				}
			}
			else {
				FL_DBG(_log, "In middle triangle area");
				if (dx < 0.5) {
					FL_DBG(_log, "In left triangles");
					if (ptInTriangle(ExactModelCoordinate(dx, dy),
					                 ExactModelCoordinate(0, VERTICAL_MULTIP * HEX_EDGE_HALF),
					                 ExactModelCoordinate(0, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
					                 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
					                 )) {
						FL_DBG(_log, "..lower part");
						result = ModelCoordinate(x, y+1);
					} else {
						FL_DBG(_log, "..upper part");
						result = ModelCoordinate(x, y);
					}
				} else {
					FL_DBG(_log, "In right triangles");
					if (ptInTriangle(ExactModelCoordinate(dx, dy),
					                 ExactModelCoordinate(1, VERTICAL_MULTIP * HEX_EDGE_HALF),
					                 ExactModelCoordinate(1, VERTICAL_MULTIP * (1-HEX_EDGE_HALF)),
					                 ExactModelCoordinate(0.5, VERTICAL_MULTIP * (1-HEX_EDGE_HALF))
					                 )) {
					        FL_DBG(_log, "..lower part");
						result = ModelCoordinate(x+1, y+1);
					} else {
						FL_DBG(_log, "..upper part");
						result = ModelCoordinate(x, y);
					}
				}
			}
		}
		FL_DBG(_log, LMsg("  result = ") << result);
		return result;
	}
Beispiel #12
0
static int flash_smart_write(struct blocklevel_device *bl, uint64_t dst, const void *src, uint64_t size)
{
	struct flash_chip *c = container_of(bl, struct flash_chip, bl);
	uint32_t er_size = c->min_erase_mask + 1;
	uint32_t end = dst + size;
	int rc;

	/* Some sanity checking */
	if (end <= dst || !size || end > c->tsize) {
		FL_DBG("LIBFLASH: Smart write param error\n");
		return FLASH_ERR_PARM_ERROR;
	}

	FL_DBG("LIBFLASH: Smart writing to 0x%" PRIx64 "..0%" PRIx64 "...\n",
	       dst, dst + size);

	/* As long as we have something to write ... */
	while(dst < end) {
		uint32_t page, off, chunk;
		enum sm_comp_res sr;

		/* Figure out which erase page we are in and read it */
		page = dst & ~c->min_erase_mask;
		off = dst & c->min_erase_mask;
		FL_DBG("LIBFLASH:   reading page 0x%08x..0x%08x...",
		       page, page + er_size);
		rc = flash_read(bl, page, c->smart_buf, er_size);
		if (rc) {
			FL_DBG(" error %d!\n", rc);
			return rc;
		}

		/* Locate the chunk of data we are working on */
		chunk = er_size - off;
		if (size < chunk)
			chunk = size;

		/* Compare against what we are writing and ff */
		sr = flash_smart_comp(c, src, off, chunk);
		switch(sr) {
		case sm_no_change:
			/* Identical, skip it */
			FL_DBG(" same !\n");
			break;
		case sm_need_write:
			/* Just needs writing over */
			FL_DBG(" need write !\n");
			rc = flash_write(bl, dst, src, chunk, true);
			if (rc) {
				FL_DBG("LIBFLASH: Write error %d !\n", rc);
				return rc;
			}
			break;
		case sm_need_erase:
			FL_DBG(" need erase !\n");
			rc = flash_erase(bl, page, er_size);
			if (rc) {
				FL_DBG("LIBFLASH: erase error %d !\n", rc);
				return rc;
			}
			/* Then update the portion of the buffer and write the block */
			memcpy(c->smart_buf + off, src, chunk);
			rc = flash_write(bl, page, c->smart_buf, er_size, true);
			if (rc) {
				FL_DBG("LIBFLASH: write error %d !\n", rc);
				return rc;
			}
			break;
		}
		dst += chunk;
		src += chunk;
		size -= chunk;
	}
	return 0;
}
Beispiel #13
0
void LayerCache::update(Camera::Transform transform, RenderList& renderlist) {
    const double OVERDRAW = 2.5;
    renderlist.clear();
    m_needupdate = false;
    if(!m_layer->areInstancesVisible()) {
        FL_DBG(_log, "Layer instances hidden");
        return;
    }
    bool isWarped = transform == Camera::WarpedTransform;
    if( isWarped ) {
        fullUpdate();
    }

    Rect viewport = m_camera->getViewPort();
    Rect screen_viewport = viewport;
    double zoom = m_camera->getZoom();
    DoublePoint3D viewport_a = m_camera->screenToVirtualScreen(Point3D(viewport.x, viewport.y));
    DoublePoint3D viewport_b = m_camera->screenToVirtualScreen(Point3D(viewport.right(), viewport.bottom()));
    viewport.x = static_cast<int32_t>(std::min(viewport_a.x, viewport_b.x));
    viewport.y = static_cast<int32_t>(std::min(viewport_a.y, viewport_b.y));
    viewport.w = static_cast<int32_t>(std::max(viewport_a.x, viewport_b.x) - viewport.x);
    viewport.h = static_cast<int32_t>(std::max(viewport_a.y, viewport_b.y) - viewport.y);
    uint8_t layer_trans = m_layer->getLayerTransparency();

    double zmin = 0.0, zmax = 0.0;

    // FL_LOG(_log, LMsg("camera-update viewport") << viewport);
    std::vector<int32_t> index_list;
    collect(viewport, index_list);
    for(unsigned i=0; i!=index_list.size(); ++i) {
        Entry& entry = m_entries[index_list[i]];
        // NOTE
        // An update is forced if the item has an animation/action.
        // This update only happens if it is _already_ included in the viewport
        // Nevertheless: Moving instances - which might move into the viewport will be updated
        // By the layer change listener.
        if(entry.force_update || !isWarped) {
            updateEntry(entry);
        }

        RenderItem& item = m_instances[entry.instance_index];
        InstanceVisual* visual = item.instance->getVisual<InstanceVisual>();
        bool visible = (visual->isVisible() != 0);
        uint8_t instance_trans = visual->getTransparency();
        if(!item.image || !visible || (instance_trans == 255 && layer_trans == 0)
                || (instance_trans == 0 && layer_trans == 255)) {
            continue;
        }

        if(layer_trans != 0) {
            if(instance_trans != 0) {
                uint8_t calc_trans = layer_trans - instance_trans;
                if(calc_trans >= 0) {
                    instance_trans = calc_trans;
                } else {
                    instance_trans = 0;
                }
            } else {
                instance_trans = layer_trans;
            }
        }

        Point3D screen_point = m_camera->virtualScreenToScreen(item.screenpoint);
        // NOTE:
        // One would expect this to be necessary here,
        // however it works the same without, sofar
        // m_camera->calculateZValue(screen_point);
        // item.screenpoint.z = -screen_point.z;

        item.dimensions.x = screen_point.x;
        item.dimensions.y = screen_point.y;
        item.dimensions.w = item.bbox.w;
        item.dimensions.h = item.bbox.h;

        item.transparency = 255 - instance_trans;

        if (zoom != 1.0) {
            // NOTE: Due to image alignment, there is additional additions on image dimensions
            //       There's probabaly some better solution for this, but works "good enough" for now.
            //       In case additions are removed, gaps appear between tiles.
            item.dimensions.w = unsigned(double(item.bbox.w) * zoom + OVERDRAW);
            item.dimensions.h = unsigned(double(item.bbox.h) * zoom + OVERDRAW);
        }

        if (!m_need_sorting) {
            zmin = std::min(zmin, item.screenpoint.z);
            zmax = std::max(zmax, item.screenpoint.z);
        }

        if(item.dimensions.intersects(screen_viewport)) {
            renderlist.push_back(&item);
        }
    }

    if (m_need_sorting) {
        InstanceDistanceSort ids;
        std::stable_sort(renderlist.begin(), renderlist.end(), ids);
    } else {
        zmin -= 0.5;
        zmax += 0.5;

        // We want to put every z value in [-10,10] range.
        // To do it, we simply solve
        // { y1 = a*x1 + b
        // { y2 = a*x2 + b
        // where [y1,y2]' = [-10,10]' is required z range,
        // and [x1,x2]' is expected min,max z coords.
        double det = zmin - zmax;
        if (fabs(det) > FLT_EPSILON) {
            double det_a = -10.0 - 10.0;
            double det_b = 10.0 * zmin - (-10.0) * zmax;
            double a = static_cast<float>(det_a / det);
            double b = static_cast<float>(det_b / det);
            float estimate = sqrtf(static_cast<float>(renderlist.size()));
            float stack_delta = fabs(-10.0f - 10.0f) / estimate * 0.1f;

            RenderList::iterator it = renderlist.begin();
            for ( ; it != renderlist.end(); ++it) {
                double& z = (*it)->screenpoint.z;
                z = a * z + b;
                InstanceVisual* vis = (*it)->instance->getVisual<InstanceVisual>();
                z += vis->getStackPosition() * stack_delta;
            }
        }
    }
    //  FL_LOG(_log, LMsg("camera-update ") << " N=" <<renderlist.size() << "/" << m_instances.size() << "/" << index_list.size());
}
Beispiel #14
0
static bool insert_bl_prot_range(struct blocklevel_range *ranges, struct bl_prot_range range)
{
	int i;
	uint32_t pos, len;
	struct bl_prot_range *prot = ranges->prot;

	pos = range.start;
	len = range.len;

	if (len == 0)
		return true;

	/* Check for overflow */
	if (pos + len < len)
		return false;

	for (i = 0; i < ranges->n_prot && len > 0; i++) {
		if (prot[i].start <= pos && prot[i].start + prot[i].len >= pos + len) {
			len = 0;
			break; /* Might as well, the next two conditions can't be true */
		}

		/* Can easily extend this down just by adjusting start */
		if (pos <= prot[i].start && pos + len >= prot[i].start) {
			FL_DBG("%s: extending start down\n", __func__);
			prot[i].len += prot[i].start - pos;
			prot[i].start = pos;
			pos += prot[i].len;
			if (prot[i].len >= len)
				len = 0;
			else
				len -= prot[i].len;
		}

		/*
		 * Jump over this range but the new range might be so big that
		 * theres a chunk after
		 */
		if (pos >= prot[i].start && pos < prot[i].start + prot[i].len) {
			FL_DBG("%s: fits within current range ", __func__);
			if (prot[i].start + prot[i].len - pos > len) {
				FL_DBG("but there is some extra at the end\n");
				len -= prot[i].start + prot[i].len - pos;
				pos = prot[i].start + prot[i].len;
			} else {
				FL_DBG("\n");
				len = 0;
			}
		}
		/*
		 * This condition will be true if the range is smaller than
		 * the current range, therefore it should go here!
		 */
		if (pos < prot[i].start && pos + len <= prot[i].start)
			break;
	}

	if (len) {
		int insert_pos = i;
		struct bl_prot_range *new_ranges = ranges->prot;

		FL_DBG("%s: adding 0x%08x..0x%08x\n", __func__, pos, pos + len);

		if (ranges->n_prot == ranges->total_prot) {
			new_ranges = realloc(ranges->prot,
					sizeof(range) * ((ranges->n_prot) + PROT_REALLOC_NUM));
			if (!new_ranges)
				return false;
			ranges->total_prot += PROT_REALLOC_NUM;
		}
		if (insert_pos != ranges->n_prot)
			for (i = ranges->n_prot; i > insert_pos; i--)
				memcpy(&new_ranges[i], &new_ranges[i - 1], sizeof(range));
		range.start = pos;
		range.len = len;
		memcpy(&new_ranges[insert_pos], &range, sizeof(range));
		ranges->prot = new_ranges;
		ranges->n_prot++;
		prot = new_ranges;
	}

	return true;
}
Beispiel #15
0
int blocklevel_smart_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
{
	uint64_t block_size;
	void *erase_buf;
	int rc;

	if (!bl) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

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

	/* Nothing smart needs to be done, pos and len are aligned */
	if ((pos & bl->erase_mask) == 0 && (len & bl->erase_mask) == 0) {
		FL_DBG("%s: Skipping smarts everything is aligned 0x%" PRIx64 " 0x%" PRIx64
				"to 0x%08x\n", __func__, pos, len, bl->erase_mask);
		return blocklevel_erase(bl, pos, len);
	}
	block_size = bl->erase_mask + 1;
	erase_buf = malloc(block_size);
	if (!erase_buf) {
		errno = ENOMEM;
		return FLASH_ERR_MALLOC_FAILED;
	}

	rc = reacquire(bl);
	if (rc) {
		free(erase_buf);
		return rc;
	}

	if (pos & bl->erase_mask) {
		/*
		 * base_pos and base_len are the values in the first erase
		 * block that we need to preserve: the region up to pos.
		 */
		uint64_t base_pos = pos & ~(bl->erase_mask);
		uint64_t base_len = pos - base_pos;

		FL_DBG("%s: preserving 0x%" PRIx64 "..0x%" PRIx64 "\n",
				__func__, base_pos, base_pos + base_len);

		/*
		 * Read the entire block in case this is the ONLY block we're
		 * modifying, we may need the end chunk of it later
		 */
		rc = bl->read(bl, base_pos, erase_buf, block_size);
		if (rc)
			goto out;

		rc = bl->erase(bl, base_pos, block_size);
		if (rc)
			goto out;

		rc = bl->write(bl, base_pos, erase_buf, base_len);
		if (rc)
			goto out;

		/*
		 * The requested erase fits entirely into this erase block and
		 * so we need to write back the chunk at the end of the block
		 */
		if (base_pos + base_len + len < base_pos + block_size) {
			rc = bl->write(bl, pos + len, erase_buf + base_len + len,
					block_size - base_len - len);
			FL_DBG("%s: Early exit, everything was in one erase block\n",
					__func__);
			goto out;
		}

		pos += block_size - base_len;
		len -= block_size - base_len;
	}

	/* Now we should be aligned, best to double check */
	if (pos & bl->erase_mask) {
		FL_DBG("%s:pos 0x%" PRIx64 " isn't erase_mask 0x%08x aligned\n",
			   	__func__, pos, bl->erase_mask);
		rc = FLASH_ERR_PARM_ERROR;
		goto out;
	}

	if (len & ~(bl->erase_mask)) {
		rc = bl->erase(bl, pos, len & ~(bl->erase_mask));
		if (rc)
			goto out;

		pos += len & ~(bl->erase_mask);
		len -= len & ~(bl->erase_mask);
	}

	/* Length should be less than a block now */
	if (len > block_size) {
		FL_DBG("%s: len 0x%" PRIx64 " is still exceeds block_size 0x%" PRIx64 "\n",
				__func__, len, block_size);
		rc = FLASH_ERR_PARM_ERROR;
		goto out;
	}

	if (len & bl->erase_mask) {
		/*
		 * top_pos is the first byte that must be preserved and
		 * top_len is the length from top_pos to the end of the erase
		 * block: the region that must be preserved
		 */
		uint64_t top_pos = pos + len;
		uint64_t top_len = block_size - len;

		FL_DBG("%s: preserving 0x%" PRIx64 "..0x%" PRIx64 "\n",
				__func__, top_pos, top_pos + top_len);

		rc = bl->read(bl, top_pos, erase_buf, top_len);
		if (rc)
			goto out;

		rc = bl->erase(bl, pos, block_size);
		if (rc)
			goto out;

		rc = bl->write(bl, top_pos, erase_buf, top_len);
		if (rc)
			goto out;
	}

out:
	free(erase_buf);
	release(bl);
	return rc;
}
Beispiel #16
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;
}
Beispiel #17
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;
}
Beispiel #18
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;
}
Beispiel #19
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;
}
Beispiel #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;
}
Beispiel #21
0
int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)
{
	uint32_t erase_size;
	const void *write_buf = buf;
	void *write_buf_start = NULL;
	uint64_t ecc_start;
	void *erase_buf;
	int rc = 0;

	if (!write_buf || !bl) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

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

	if (!(bl->flags & WRITE_NEED_ERASE)) {
		FL_DBG("%s: backend doesn't need erase\n", __func__);
		return blocklevel_write(bl, pos, buf, len);
	}

	rc = blocklevel_get_info(bl, NULL, NULL, &erase_size);
	if (rc)
		return rc;

	if (ecc_protected(bl, pos, len, &ecc_start)) {
		FL_DBG("%s: region has ECC\n", __func__);

		len = ecc_buffer_size(len);

		write_buf_start = malloc(len);
		if (!write_buf_start) {
			errno = ENOMEM;
			return FLASH_ERR_MALLOC_FAILED;
		}

		if (memcpy_to_ecc(write_buf_start, buf, ecc_buffer_size_minus_ecc(len))) {
			free(write_buf_start);
			errno = EBADF;
			return FLASH_ERR_ECC_INVALID;
		}
		write_buf = write_buf_start;
	}

	erase_buf = malloc(erase_size);
	if (!erase_buf) {
		errno = ENOMEM;
		rc = FLASH_ERR_MALLOC_FAILED;
		goto out_free;
	}

	rc = reacquire(bl);
	if (rc)
		goto out_free;

	while (len > 0) {
		uint32_t erase_block = pos & ~(erase_size - 1);
		uint32_t block_offset = pos & (erase_size - 1);
		uint32_t size = erase_size > len ? len : erase_size;
		int cmp;

		/* Write crosses an erase boundary, shrink the write to the boundary */
		if (erase_size < block_offset + size) {
			size = erase_size - block_offset;
		}

		rc = bl->read(bl, erase_block, erase_buf, erase_size);
		if (rc)
			goto out;

		cmp = blocklevel_flashcmp(erase_buf + block_offset, write_buf, size);
		FL_DBG("%s: region 0x%08x..0x%08x ", __func__,
				erase_block, erase_size);
		if (cmp != 0) {
			FL_DBG("needs ");
			if (cmp == -1) {
				FL_DBG("erase and ");
				bl->erase(bl, erase_block, erase_size);
			}
			FL_DBG("write\n");
			memcpy(erase_buf + block_offset, write_buf, size);
			rc = bl->write(bl, erase_block, erase_buf, erase_size);
			if (rc)
				goto out;
		}
		len -= size;
		pos += size;
		write_buf += size;
	}

out:
	release(bl);
out_free:
	free(write_buf_start);
	free(erase_buf);
	return rc;
}
Beispiel #22
0
	ModelCoordinate HexGrid::toLayerCoordinates(const ExactModelCoordinate& map_coord) {
		FL_DBG(_log, LMsg("==============\nConverting map coords ") << map_coord << " to int32_t layer coords...");
		ExactModelCoordinate elc = m_inverse_matrix * map_coord;
		elc.y *= VERTICAL_MULTIP_INV;
		return toLayerCoordinatesHelper(elc);
	}
Beispiel #23
0
static int ffs_num_entries(struct ffs_hdr *hdr)
{
	if (hdr->count == 0)
		FL_DBG("%s returned zero!\n", __func__);
	return hdr->count;
}
VFSDirectory::VFSDirectory(VFS* vfs, const std::string& root) : VFSSource(vfs), m_root(root) {
    FL_DBG(_log, LMsg("VFSDirectory created with root path ") << m_root);
    if(!m_root.empty() && *(m_root.end() - 1) != '/')
        m_root.append(1,'/');
}