Example #1
0
static int hasDeviceInfoBBT() {
	int bank;
	int good = TRUE;
	for(bank = 0; bank < Data->banksTotal; bank++) {
		good = findDeviceInfoBBT(bank, NULL);
		if(!good)
			return FALSE;
	}

	return good;
}
Example #2
0
static bool hasDeviceInfoBBT(void)
{
	int bank;
	bool good = true;
	for(bank = 0; bank < NANDGeometry->banksTotal; bank++) {
		good = findDeviceInfoBBT(bank, NULL);
		if(!good)
			return false;
	}

	return good;
}
Example #3
0
int VFL_Open(void)
{
	void* FTLCtrlBlock;
	u16 buffer[3];

	int bank = 0;
	for(bank = 0; bank < NANDGeometry->banksTotal; bank++) {
		VFLCxt* curVFLCxt;
		int i;
		int minUsn;
		int VFLCxtIdx;
		int last;
		int page;

		if(!findDeviceInfoBBT(bank, pstBBTArea)) {
			LOG("ftl: findDeviceInfoBBT failed\n");
			return -1;
		}

		if(bank >= NANDGeometry->banksTotal) {
			return -1;
		}

		curVFLCxt = &pstVFLCxt[bank];

		// Any VFLCxt page will contain an up-to-date list of all blocks used to store VFLCxt pages. Find any such
		// page in the system area.

		for(i = 1; i < FTLData->sysSuBlks; i++) {
			// so pstBBTArea is a bit array of some sort
			if(!(pstBBTArea[i / 8] & (1 << (i  & 0x7))))
				continue;

			if(nand_read_vfl_cxt_page(bank, i, 0, PageBuffer, SpareBuffer) == true) {
				memcpy(curVFLCxt->VFLCxtBlock, ((VFLCxt*)PageBuffer)->VFLCxtBlock, sizeof(curVFLCxt->VFLCxtBlock));
				break;
			}
		}

		if(i == FTLData->sysSuBlks) {
			LOG("ftl: cannot find readable VFLCxtBlock\n");
			return -1;
		}

		// Since VFLCxtBlock is a ringbuffer, if blockA.page0.spare.usnDec < blockB.page0.usnDec, then for any page a
	        // in blockA and any page b in blockB, a.spare.usNDec < b.spare.usnDec. Therefore, to begin finding the
		// page/VFLCxt with the lowest usnDec, we should just look at the first page of each block in the ring.
		minUsn = 0xFFFFFFFF;
		VFLCxtIdx = 4;
		for(i = 0; i < 4; i++) {
			SpareData* spareData;
			u16 block = curVFLCxt->VFLCxtBlock[i];
			if(block == 0xFFFF)
				continue;

			if(nand_read_vfl_cxt_page(bank, block, 0, PageBuffer, SpareBuffer) != true)
				continue;

			spareData = (SpareData*) SpareBuffer;
			if(spareData->meta.usnDec > 0 && spareData->meta.usnDec <= minUsn) {
				minUsn = spareData->meta.usnDec;
				VFLCxtIdx = i;
			}
		}

		if(VFLCxtIdx == 4) {
			LOG("ftl: cannot find readable VFLCxtBlock index in spares\n");
			return -1;
		}

		// VFLCxts are stored in the block such that they are duplicated 8 times. Therefore, we only need to
		// read every 8th page, and nand_read_vfl_cxt_page will try the 7 subsequent pages if the first was
		// no good. The last non-blank page will have the lowest spare.usnDec and highest usnInc for VFLCxt
		// in all the land (and is the newest).
		last = 0;
		for(page = 8; page < NANDGeometry->pagesPerBlock; page += 8) {
			if(nand_read_vfl_cxt_page(bank, curVFLCxt->VFLCxtBlock[VFLCxtIdx], page, PageBuffer, SpareBuffer) == false) {
				break;
			}

			last = page;
		}

		if(nand_read_vfl_cxt_page(bank, curVFLCxt->VFLCxtBlock[VFLCxtIdx], last, PageBuffer, SpareBuffer) == false) {
			LOG("ftl: cannot find readable VFLCxt\n");
			return -1;
		}

		// Aha, so the upshot is that this finds the VFLCxt and copies it into pstVFLCxt
		memcpy(&pstVFLCxt[bank], PageBuffer, sizeof(VFLCxt));

		// This is the newest VFLCxt across all banks
		if(curVFLCxt->usnInc >= curVFLusnInc) {
			curVFLusnInc = curVFLCxt->usnInc;
		}

		// Verify the checksum
		if(vfl_check_checksum(bank) == false) {
			LOG("ftl: VFLCxt has bad checksum\n");
			return -1;
		}
	}

	// retrieve the FTL control blocks from the latest VFL across all banks.
	FTLCtrlBlock = VFL_GetFTLCtrlBlock();

	// Need a buffer because eventually we'll copy over the source
	memcpy(buffer, FTLCtrlBlock, sizeof(buffer));

	// Then we update the VFLCxts on every bank with that information.
	for(bank = 0; bank < NANDGeometry->banksTotal; bank++) {
		memcpy(pstVFLCxt[bank].FTLCtrlBlock, buffer, sizeof(buffer));
		vfl_gen_checksum(bank);
	}

	return 0;
}
Example #4
0
static int VFL_Open() {
	int bank = 0;
	for(bank = 0; bank < Data->banksTotal; bank++) {
		if(!findDeviceInfoBBT(bank, pstBBTArea)) {
			bufferPrintf("ftl: findDeviceInfoBBT failed\r\n");
			return -1;
		}

		if(bank >= Data->banksTotal) {
			return -1;
		}


		VFLCxt* curVFLCxt = &pstVFLCxt[bank];
		uint8_t* pageBuffer = malloc(Data->bytesPerPage);
		uint8_t* spareBuffer = malloc(Data->bytesPerSpare);
		if(pageBuffer == NULL || spareBuffer == NULL) {
			bufferPrintf("ftl: cannot allocate page and spare buffer\r\n");
			return -1;
		}

		int i = 1;
		for(i = 1; i < Data2->field_0; i++) {
			// so pstBBTArea is a bit array of some sort
			if(!(pstBBTArea[i / 8] & (1 << (i  & 0x7))))
				continue;

			if(vfl_read_page(bank, i, 0, pageBuffer, spareBuffer) == TRUE) {
				memcpy(curVFLCxt->VFLCxtBlock, ((VFLCxt*)pageBuffer)->VFLCxtBlock, sizeof(curVFLCxt->VFLCxtBlock));
				break;
			}
		}

		if(i == Data2->field_0) {
			bufferPrintf("ftl: cannot find readable VFLCxtBlock\r\n");
			free(pageBuffer);
			free(spareBuffer);
			return -1;
		}

		int minLpn = 0xFFFFFFFF;
		int VFLCxtIdx = 4;
		for(i = 0; i < 4; i++) {
			uint16_t block = curVFLCxt->VFLCxtBlock[i];
			if(block == 0xFFFF)
				continue;

			if(vfl_read_page(bank, block, 0, pageBuffer, spareBuffer) != TRUE)
				continue;

			SpareData* spareData = (SpareData*) spareBuffer;
			if(spareData->logicalPageNumber > 0 && spareData->logicalPageNumber <= minLpn) {
				minLpn = spareData->logicalPageNumber;
				VFLCxtIdx = i;
			}
		}

		if(VFLCxtIdx == 4) {
			bufferPrintf("ftl: cannot find readable VFLCxtBlock index in spares\r\n");
			free(pageBuffer);
			free(spareBuffer);
			return -1;
		}

		int page = 8;
		int last = 0;
		for(page = 8; page < Data->pagesPerBlock; page += 8) {
			if(vfl_read_page(bank, curVFLCxt->VFLCxtBlock[VFLCxtIdx], page, pageBuffer, spareBuffer) == FALSE) {
				break;
			}
			
			last = page;
		}

		if(vfl_read_page(bank, curVFLCxt->VFLCxtBlock[VFLCxtIdx], last, pageBuffer, spareBuffer) == FALSE) {
			bufferPrintf("ftl: cannot find readable VFLCxt\n");
			free(pageBuffer);
			free(spareBuffer);
			return -1;
		}

		// Aha, so the upshot is that this finds the VFLCxt and copies it into pstVFLCxt
		memcpy(&pstVFLCxt[bank], pageBuffer, sizeof(VFLCxt));
		if(curVFLCxt->field_0 >= VFLData4) {
			VFLData4 = curVFLCxt->field_0;
		}

		free(pageBuffer);
		free(spareBuffer);

		if(vfl_check_checksum(bank) == FALSE) {
			bufferPrintf("ftl: VFLCxt has bad checksum\n");
			return -1;
		}
	} 

	void* maxThing = VFL_get_maxThing();
	uint16_t buffer[3];

	memcpy(buffer, maxThing, 6);

	for(bank = 0; bank < Data->banksTotal; bank++) {
		memcpy(pstVFLCxt[bank].field_4, buffer, sizeof(buffer));
		vfl_gen_checksum(bank);
	}

	return 0;
}