Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 564b8497 authored by Guillaume LECERF's avatar Guillaume LECERF Committed by David Woodhouse
Browse files

mtd: cfi_cmdset_0002: do not fail on no extended query table as they are both optional

After looking at AMD's CFI specification [1], both of the extended query
tables are optional. Thus, it looks like relying that at least one of
those tables exist is a bug in cfi_cmdset_0002.

This patch inverts the logic and checks for unlock function pointers before
exiting on error. This approach leaves place to add a call to a fixup
function to try to handle chips compatible with the early AMD specification
from 1995 [2].

[1] http://www.amd.com/us-en/assets/content_type/DownloadableAssets/cfi_r20.pdf
[2] http://noel.feld.cvut.cz/hw/amd/20158a.pdf



Signed-off-by: default avatarGuillaume LECERF <glecerf@gmail.com>
Reviewed-by: default avatarWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 58598861
Loading
Loading
Loading
Loading
+45 −44
Original line number Diff line number Diff line
@@ -357,20 +357,15 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)

	if (cfi->cfi_mode==CFI_MODE_CFI){
		unsigned char bootloc;
		/*
		 * It's a real CFI chip, not one for which the probe
		 * routine faked a CFI structure. So we read the feature
		 * table from it.
		 */
		__u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
		struct cfi_pri_amdstd *extp;

		extp = (struct cfi_pri_amdstd*)cfi_read_pri(map, adr, sizeof(*extp), "Amd/Fujitsu");
		if (!extp) {
			kfree(mtd);
			return NULL;
		}

		if (extp) {
			/*
			 * It's a real CFI chip, not one for which the probe
			 * routine faked a CFI structure.
			 */
			cfi_fixup_major_minor(cfi, extp);

			if (extp->MajorVersion != '1' ||
@@ -416,6 +411,12 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
			/* Set the default CFI lock/unlock addresses */
			cfi->addr_unlock1 = 0x555;
			cfi->addr_unlock2 = 0x2aa;
		}

		if (!cfi->addr_unlock1 || !cfi->addr_unlock2) {
			kfree(mtd);
			return NULL;
		}

	} /* CFI mode */
	else if (cfi->cfi_mode == CFI_MODE_JEDEC) {