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); }
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; }
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; }
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; }
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; }
/** * 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; }
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(); }
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); }
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"); } }
/* 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; }
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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }