From owner-svn-src-all@FreeBSD.ORG Fri Nov 15 23:37:34 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 45D4A613; Fri, 15 Nov 2013 23:37:34 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 1B13B2C56; Fri, 15 Nov 2013 23:37:34 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rAFNbXD6031961; Fri, 15 Nov 2013 23:37:33 GMT (envelope-from ian@svn.freebsd.org) Received: (from ian@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rAFNbXJp031960; Fri, 15 Nov 2013 23:37:33 GMT (envelope-from ian@svn.freebsd.org) Message-Id: <201311152337.rAFNbXJp031960@svn.freebsd.org> From: Ian Lepore Date: Fri, 15 Nov 2013 23:37:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r258199 - head/sys/dev/nand X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Nov 2013 23:37:34 -0000 Author: ian Date: Fri Nov 15 23:37:33 2013 New Revision: 258199 URL: http://svnweb.freebsd.org/changeset/base/258199 Log: Search for and validate the ONFI params as specified in the standard. The ONFI spec states that at least two bytes of the signature ("ONFI") must be present, and the CRC must be correct to have a valid parameter page. If the page is not valid there are at least two backup pages where the data can also be found. Submitted by: Kristof Provost (cleanup) and me (orig). Modified: head/sys/dev/nand/nand_generic.c Modified: head/sys/dev/nand/nand_generic.c ============================================================================== --- head/sys/dev/nand/nand_generic.c Fri Nov 15 23:35:45 2013 (r258198) +++ head/sys/dev/nand/nand_generic.c Fri Nov 15 23:37:33 2013 (r258199) @@ -319,10 +319,31 @@ check_fail(device_t nandbus) return (0); } +static uint16_t +onfi_crc(const void *buf, size_t buflen) +{ + int i, j; + uint16_t crc; + const uint8_t *bufptr; + + bufptr = buf; + crc = 0x4f4e; + for (j = 0; j < buflen; j++) { + crc ^= *bufptr++ << 8; + for (i = 0; i < 8; i++) + if (crc & 0x8000) + crc = (crc << 1) ^ 0x8005; + else + crc <<= 1; + } + return crc; +} + static int onfi_read_parameter(struct nand_chip *chip, struct onfi_params *params) { device_t nandbus; + int found, sigcount, trycopy; nand_debug(NDBG_GEN,"read parameter"); @@ -339,16 +360,32 @@ onfi_read_parameter(struct nand_chip *ch if (NANDBUS_START_COMMAND(nandbus)) return (ENXIO); - NANDBUS_READ_BUFFER(nandbus, params, sizeof(struct onfi_params)); - - if (memcmp(params->signature, "ONFI", sizeof(params->signature))) { - device_printf(chip->dev, "Error: bad signature\n"); - return (ENXIO); + /* + * XXX Bogus DELAY, we really need a nandbus_wait_ready() here, but it's + * not accessible from here (static to nandbus). + */ + DELAY(1000); + + /* + * The ONFI spec mandates a minimum of three copies of the parameter + * data, so loop up to 3 times trying to find good data. Each copy is + * validated by a signature of "ONFI" and a crc. There is a very strange + * rule that the signature is valid if any 2 of the 4 bytes are correct. + */ + for (found= 0, trycopy = 0; !found && trycopy < 3; trycopy++) { + NANDBUS_READ_BUFFER(nandbus, params, sizeof(struct onfi_params)); + sigcount = params->signature[0] == 'O'; + sigcount += params->signature[1] == 'N'; + sigcount += params->signature[2] == 'F'; + sigcount += params->signature[3] == 'I'; + if (sigcount < 2) + continue; + if (onfi_crc(params, 254) != params->crc) + continue; + found = 1; } - - /* TODO */ - /* Check CRC */ - /* Use redundant page if necessary */ + if (!found) + return (ENXIO); return (0); }